Where to use volatile keyword in C
I know that the volatile keyword prevents the compiler from optimizing the variable and reading it from memory whenever it is read. Apart from memory mapped registers, what are all the situations where we need to use mutability? Given a compatible compiler, is it necessary to declare test_var as volatile in both scenarios?
1.
In file1.c
int test_var=100;
void func1()
{
test_var++;
}
In file2.c
extern int test_var;
void func2()
{
if(test_var==100)
{
....
}
}
2.
In file1.c
int test_var=100;
void func1()
{
}
In file2.c
extern int test_var;
void func2()
{
if(test_var==100)
{
....
}
}
source to share
memory mapped by I / O is only common use volatile
in C. *)
With POSIX signals, a volatile
can also be used in conjunction with a type sig_atomic_t
as follows:
volatile sig_atomic_t signal_occured = 0;
None of your scripts should require volatile
at all. If all you're interested in is guaranteeing that the value is updated between different compilation units, see tofro's comment extern
already guarantees that. In particular, volatile
not the correct tool for synchronizing threads in C. It will only introduce errors because, as you claim, it does , requires actual read and write access to the variable, but it does not enforce their correct ordering with respect to the streams (for there are no memory shortcomings, google).
Note that this differs from some other languages ββwhere it is volatile
designed to work between threads.
On an embedded system, it volatile
can be good enough for communication between the ISR (Interrupt Service Service) and the main program, combined with a data type that is read / written atomically, just like sig_atomic_t
for POSIX signals.For this, refer to your compiler's documentation.
*). The C standard mentions this, along with the "asynchronously terminating functions" use case, only in a footnote, since memory mapped I / O is outside of the language. The language simply defines semantics volatile
in such a way as to make it suitable for memory mapped I / O.
source to share
No need for any of your examples volatile
.
volatile
it is necessary:
- anywhere a variable can be changed outside the control of one thread of execution,
- wherever variable access is required, even if it is semantically ineffective.
Case 1 includes:
- memory mapped I / O registers,
- memory used for DMA transfers,
- memory shared between interrupt and / or thread contexts,
- memory shared between independent processors (for example, dual-port RAM)
Case 2 includes:
- loop counters used for empty dwell loops where the entire loop can be fully optimized and will not take time,
- Variables written but never readable for observation in the debugger.
The above examples may not be exhaustive, but semantics are key volatile
; the language should only do explicit access as stated in the source code.
source to share
In microcontroller C applications using interrupts, the keyword is volatile
important to ensure that the value set in the interrupt is stored correctly in the interrupt and later has the correct value in the main loop processing. Failure to use volatile
is perhaps the single biggest reason why timer based interrupts or ADC (analog to digital conversion) interrupts, for example, will have a corrupted value when the control flow resumes after returning the processor state after an interrupt. 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 volatile
it, it will not guarantee that it will not work as expected.
source to share