I know volatile keyword prevents compiler from optimizing a variable and read it from memory whenever it is read. Apart from memory mapped registers, what are all the situat
Apart from memory mapped registers, what are all the situations where we need to use volatile?
If
longjmp
;then you probably have no need for volatile.
In neither of your examples is volatile
necessary.
volatile
is necessary:
Case 1 includes:
Case 2 includes:
The above examples may not be exhaustive, but it is the semantics of volatile
that are key; the language only has to perform an explicit access as indicated by the source code.
Besides extensions such as memory mapped devices, in standard C volatile
has two use cases: interaction with signal handlers and modification of objects across usage of setjmp/longjmp
. Both are case were there is unusual flow of control that an optimizer may not be aware of.
In C microcontroller applications using interrupts, the volatile
keyword is essential in making sure that a value set in an interrupt is saved properly in the interrupt and later has the correct value in the main processing loop. Failure to use volatile
is perhaps the single biggest reason that timer-based interrupts or ADC (analog-digital conversion) based interrupts for example will have a corrupted value when flow of control resumes after the processor state is returned post-interrupt. A canonical template from Atmel and GCC:
volatile uint8_t flag = 0;
ISR(TIMER_whatever_interrupt)
{
flag = 1;
}
while(1) // main loop
{
if (flag == 1)
{
<do something>
flag = 0;
}
}
Without the volatile
it's guaranteed to not work as expected.
memory mapped I/O is the only generic use of volatile
in C. *)
With POSIX signals, a volatile
can also be used together with the type sig_atomic_t
like this:
volatile sig_atomic_t signal_occured = 0;
Neither of your scenarios should require volatile
at all. If all you're interested in is a guarantee that the value is updated between different compilation units, see tofro's comment, extern
already guarantees that. Particularly, volatile
is not the correct tool for thread synchronization in C. It would only introduce bugs, because, as you state it, it does require actual read and write accesses to the variable, but it does not enforce their proper ordering with respect to threads (it's missing memory barriers, google for details).
Note that this is different from some other languages where volatile
is designed to work between threads.
In an embedded system, volatile
might be good enough for communicating between an ISR (interrupt service routine) and the main program, when combined with a data type that's read/written atomically, just like sig_atomic_t
for POSIX signals. Consult the documentation of your compiler for that.
*) The C standard mentions this, along with the use-case of "asynchronously interrupting functions", only in a footnote, because memory-mapped I/O is outside the scope of the language. The language just defines the semantics of volatile
in a way that make it suitable for memory-mapped I/O.