I am using an in-house written thread switcher.
In general, if I have two threads accessing a global variable, is the volatile keyword required for all variables accessed from different threads?
Thank you in advance.
This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
I am using an in-house written thread switcher.
In general, if I have two threads accessing a global variable, is the volatile keyword required for all variables accessed from different threads?
Thank you in advance.
I don't think you need volatile in this case. Volatile tells the compiler not to optimize accesses to the variable. One example of needing volatile is if the hardware can change the variable without the CPU (such as DMA). Then, you want to make sure that the CPU reaches out to that memory for every read instead of "caching" it in internal registers.
I believe you will need the volatile keyword. It's not just for the case when hardware (e.g. DMA or peripheral) or an interrupt might modify the variable, it's for when any external agent might either read or write the variable, and a separate thread is an external agent as far as the compiler is concerned. The standard C language does not provide any support for declaring variables that might be shared by another thread/process but are otherwise not volatile, so for now you're just going to need to use volatile. However, usually the compiler will not do much optimization of accesses to global variables because it's very difficult to prove that nothing else in the program will access them, so it is likely that you can get by without volatile, especially if you stick to optimization level -o2 or lower. Still, it is possible the compiler could optimize some accesses, so use volatile just to be sure.
It's likely TI compilers will eventually provide some language extension to identify thread-shared objects, but not soon.
I have found that the compiler does indeed perform some register optimizations that will require the volatile keyword when global variables are shared between threads. These optimizations are generated even though all optimizations are disabled (Opt Level = None), this is due to "loop invariant expressions" that are not part of the normal compiler optimizations.
From the C/C++ manual:
3.4.2 Use the Volatile Keyword for Necessary Memory Accesses
The compiler analyzes data flow to avoid memory accesses whenever possible. If you have code that
depends on memory accesses exactly as written in the C/C++ code, you must use the volatile keyword to identify these accesses. The compiler does not optimize out any references to volatile variables. In the following example, the loop waits for a location to be read as 0xFF:
unsigned int *ctrl; while (*ctrl !=0xFF); In this example, *ctrl is a loop-invariant expression, so the loop is optimized down to a single memory read. To correct this, declare ctrl as: volatile unsigned int *ctrl;