pragma Volatile (local_name);
Volatile is a representation pragma that can be used with types and variables to specify that the variable in question may suddenly change in value. For example, this may occur due to a device writing to a shared buffer.
When this pragma is used, the compiler must suppress any optimizations that would interfere with the correct reading of the volatile variables. For example, two successive readings of the same variable cannot be optimized to just one or reordered.
It is almost always incorrect to use atomic or volatile variables for tasking. When an object is atomic it just means that it will be read from or written to memory atomically. The compiler will not generate atomic instructions or memory barriers when accessing to that object, it will just:
- check that the architecture guarantees atomic memory loads and stores,
- disallow some compiler optimizations, like reordering or suppressing redundant accesses to the object.
For example, the following code, where A is an atomic object can be misunderstood:
A := A + 1; -- Not an atomic increment!
The compiler will not (and is not allowed by the Standard to) generate an atomic increment instruction to directly increment and update from memory the variable A. This is the code generated by the compiler:
A := A + 1; 804969f: a1 04 95 05 08 mov 0x8059504,%eax 80496a4: 40 inc %eax 80496a5: a3 04 95 05 08 mov %eax,0x8059504
As can be seen, no atomic increment instruction or test-and-set opcode will be generated. Like in other programming languages, if these specific instructions are required in the program they must be written explicitly using machine code insertions.
The above code snippet is equivalent to the following code (both code sequences generates exactly the same object code), where T is a (non-atomic) temporary variable:
T := A; -- A is copied atomically to local variable T T := T + 1; -- local variable T is incremented A := T; -- A is stored atomically
Thus it is incorrect to modify an atomic variable at the same time from multiple tasks. For example, two tasks incrementing a counter in parallel. Even in an uniprocessor, other Ada tasking features like a protected object should be used instead. In multiprocessors, depending on the memory consistency model, using various atomic or volatile variables for task communication can have surprising consequences. Therefore, extreme care should be taken when using atomic objects for task data sharing or synchronization, specially in a multiprocessor.
- Arch Robison (2007-11-30). "Volatile: Almost Useless for Multi-Threaded Programming". Intel Software Network. http://softwareblogs.intel.com/2007/11/30/volatile-almost-useless-for-multi-threaded-programming/. Retrieved 2008-05-30. "There is a widespread notion that the keyword volatile is good for multi-threaded programming (...) volatile is almost useless for multi-threaded programming."
- Ian Lance Taylor (2008-03-05). "Volatile". http://www.airs.com/blog/archives/154. Retrieved 2008-05-28. "Using [the C/C++ qualifier] volatile does not mean that the variable is accessed atomically; no locks are used. Using volatile does not mean that other cores in a multi-core system will see the memory accesses; no cache flushes are used. (...) Using volatile does not imply any sort of memory barrier; the processor can and will rearrange volatile memory accesses. (...) You should not use more than one such variable to communicate between any pair of threads, as there is no guarantee that the different threads will see the accesses in the same order."
- Laurent Guerby (January 1995). "C.5 Shared Variable Control". Ada 95 Rationale. Intermetrics. "A need to access specific machine instructions arises sometimes (...). Examples include instructions that perform compound operations atomically on shared memory, such as test-and-set and compare-and-swap (...)"
- Sarita V. Adve, Kourosh Gharachorloo (December 1996). "Shared Memory Consistency Models: A Tutorial". IEEE Computer 29 (12): 66–76. http://www.hpl.hp.com/techreports/Compaq-DEC/WRL-95-7.pdf. Retrieved 2008-05-28.
- This pragma is available in Ada 95 and Ada 2005 (Annex C, a specialized needs annex).
- In Ada 83 there is not an standard pragma completely equivalent to Volatile. However, pragma Shared is similar to Atomic (although it is obsolescent since Ada 95), and some compilers added an implementation-defined pragma for this purpose.
Volatile is a standard pragma since Ada 95, defined in the Systems Programming Annex (Annex C). This is a specialized needs annex, therefore this pragma is not available in those compilers not implementing that annex.
This pragma is portable to different architectures and operating systems.
In C/C++, the volatile qualifier is equivalent to this pragma. However, this C qualifier is used for both volatile and atomic data, even if atomic access is required. Therefore, when interfacing with existing C code, the programmer must read the code to understand whether the data needs atomic load and stores. If needed, the data should be marked in the Ada side with pragma Atomic or Atomic_Components, or with pragma Volatile or Volatile_Components otherwise.
Volatile objects without address clauses
In many cases, when a volatile object is used for interfacing with a hardware device it should have an address clause too.
check object_declarations (volatile_no_address);
- Ada Programming
- Ada Programming/Pragmas
- Ada Programming/Pragmas/Atomic
- Ada Programming/Pragmas/Atomic Components
- Ada Programming/Pragmas/Volatile Components
- Ada Programming/Pragmas/Shared (obsolescent)
Ada Reference Manual
Ada 95 Rationale
Ada 95 Quality and Style Guide
- Robert Dewar (1996-02-17). "pragma Shared (was Ada is almost ....)". comp.lang.ada. (Web link). Retrieved on 2008-05-28. "pragma Atomic is QUITE different from pragma Volatile. pragma Atomic in Ada is essentially identical to pragma Shared in Ada 83. pragma Volatile in Ada is essentially identical to volatile in C, and is a feature that is not available in Ada 83."
- "Implementation Defined Pragmas". GNAT Pro Reference Manual. http://www.adacore.com/wp-content/files/auto_update/gnat-unw-docs/html/gnat_rm_2.html#SEC118. Retrieved 2008-06-02. "[pragma Volatile] was supplied in some Ada 83 compilers, including DEC Ada 83. The Ada 95 / Ada 2005 implementation of pragma Volatile is upwards compatible with the implementation in DEC Ada 83."