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.
extern
storage class, the compiler is restricted in its ability to optimize out reads and writes to that variable. – Hatchway