If a global variable is changed (written) during normal execution flow and only read outside this normal flow (in an interrupt). Does this variable need to be volatile?
Yes absolutely.
And why?
To ensure proper execution of the interrupt handler (rather than the normal flow).
Let me elaborate.
Imagine you have a variable like this:
int x;
You are modifying this variable in the normal flow of the program as this:
void modify(int *x){...some code here...}
And in the interrupt service routine, you are reading the variable.
Remember that an interrupt can occur asynchronously(at any time). Also remember that the compiler will first convert your code into a series of machine instructions which could look something like this:
load val from mem to register
perform modification operations
store value from registers to memory
perform other operations where the variable is used
Now, the compiler may optimise this program to reduce the number of memory read-writes as such:
load value
perform modifications
use value
...
modify register content
...
use
...
keep using value from the registers without ever storing in the memory.
In such a case, if an interrupt occurs, (note that the interrupt context is usually different from the normal context and thus has different set of registers in a lot of architectures (say arm...)), it will attempt to read the value of the variable from the memory. But the contents of the memory have never been changed because of compiler optimisation.
So, the ISR could read an old value (worse still-we can't definitely say how old a value) which would result in unintended behaviour.
So, the variable should be declared as volatile to prevent the compiler from meddling with the program.
volatile sig_atomic_t
flag; specific platforms might provide further allowed behaviour for interrupts – Maurinemaurise_Atomic
will take care of atomicity and of needed memory barrier (no need forvolatile
). I could also manage the atomicity manually by any means and add memory barrier and it would be sufficient. – Throttle