If a variable foo is not declared as volatile, then in the case of a compiler optimization, if you use Foo for the second time, the code generated by the compiler may use the value already stored in the register instead of "reload" the variable from memory again. If this variable is already modified (often in multi-threaded situations), then the Foo in memory and the Foo in the Register are inconsistent, and the result is wrong.
Do you Volatile? Should?
by Kevin P. Dankwardt, Ph.D.
Volatile is a ANSI C type modifier that's frequently needed in C code that's part of signal/interrupt handlers , threaded code, and other kernel code, including device drivers. In general, the any data is undated asynchronously should is declared to be volatile. Incidentally, this issue are not related to CPU caches except that re-loading of variables into registers may involve cache Hits or misses.
Why use Volatile?
The reason to use volatile are to insure, the compiler generates code to re-load a data item each time it is referenced In the Your program. Without volatile, the compiler may generate code this merely re-uses the value it already loaded into a register.
Volatile advises the compiler that the data is modified in a manner, that is, is determinable by the compiler. This could was, for example, when a pointer was mapped to a device ' s hardware registers. The device may independently the values unbeknownst to the compiler.
With gcc the -o2 option was normally required to see the effect of the using volatile. Without -o2or greater optimization, the compiler is likely to re-load registers each time a variable is reference D, anyway. Don ' t blame the optimizer if a program gets incorrect results because, the program does isn't use volatile where required.
For example, if-threads share a variable, sum, and one or both threads modify it, then the other thread may u Se a stale value in a register instead of going back to memory to get the new value. Instead, each time the thread references sum, it must is re-loaded. The the-the-insure-occurs in ANSI-C is-to-declare sum to be volatile.
Example 1.
The use of the volatile can is required to get correct answers. For example the Program wrong will give incorrect results when it was compiled -o2 and Withou t volatile . This slightly obtuse program was designed to stop after ticks of a interval timer that ticks at 100Hz and print the VA Lue of the variable Total . The tick count is incremented in the signal handler. When the count gets to the should terminate. If The tick count does not get to within ten seconds then a alarm goes off and the program terminates.
By compiling the program As:gcc-o2-dvolatile=volatile Wrong.c-o Wrong_v you'll see, (unless your program is PREEMPTE D for quite a while), which the count gets to and the program terminates as designed. With the program compiled as Gcc-o2 Wrong.c-o Wrong_nvyou would see, that the count becomes greater than as shown whe n the handler prints it, but the "while" loop does not terminate.
Incidentally, attempts to determine and what's happening may thwart your. For example, a function call, such as to printf (), or the use of a breakpoint, in the loop, would likely spill and re-load The registers.
Syntax
The keyword volatile is similar to the const keyword. Volatile is used to modify a type. Thus an int, const int, pointer, etc. May is declared to be volatile. In addition, the a point is declared to being a pointer to volatile. A pointer to volatile means, the data to which the pointer refers are volatile as opposed to the pointer itself. Of course, both the pointer and to which it refers, May is declared to be volatile.
To declare a volatile int does:
volatile int v;
and to declare VP to is a pointer to a volatile int does:
volatile int *VP;
Since deciphering c declarations can be difficult a want to consult the C declaration chapter in the Sun manual. This manual references the Decoder Flowchart the can is used to help decipher declarations.
In addition, Linux May has the cdecl (1) program which can be used to translate C declarations to 中文版, as for Example, in
echo ' explain volatile int *v ' | Cdecl
Which'll answer with
Declare v as a pointer to volatile int
Reading C declarations is made simpler if you realize this they is writtenboustrophedonically. Of course, even knowing the definition of boustrophedonically doesn ' t really help. The idea was that C declarations was interpreted based on the tricky precedence of operators such as "*", "[]", and "()".
Performance issues
In some sense, volatile is the opposite of Register. Thus, one can expect to lose performance. This means doesn't use volatile when it's not needed.
Example 2.
The performance example we can see the difference, volatile may make. If We compile this program with and without volatile defined as volatile we see an average number of ITE Rations of almost 5,000 for the volatile case and almost 20,000 for the non-volatile case. yikes! Remember that we must compile both of them with the -o2 option. (These iteration counts were made on a 400Mhz amd-k6.)
Linux Examples
The use of the volatile keyword are common in the Linux kernel source. For example, of the 10,607 . C and . h files in the Fedora Core 1, Linux kernel source directory, 1,694 ha ve the string "volatile" in them somewhere. As an example, the file drivers/net/eepro.c uses volatile in three places.
385:volatile S32 Cmd_status; /* Command and Status fields. */
392:volatile S32 status;
764:volatile S32 *self_test_results;
Generated Code
By examining the code generated by the compiler one can see the difference volatile makes. In this simple example we can see the x86 assembly language when volatile is used and when volatile is not used.
Quiz yourself
What are volatile in each of the following examples? is they all legal declarations?
1) volatile int *s1;
2) int* volatile S2;
3) volatile int* volatile S3;
4) const volatile int * volatile S4;
5) Volatile int * (*F) (volatile int *);
Check your answers.
Summary
The volatile keyword is relatively unknown. There is the times when it is the required for correct operation of C + + programs. In general, whenever a variable is altered asynchronously, such as by a signal handler or mapped hardware, the VARIABL E must is declared to be volatile.
Since volatile prevents re-using values in registers, volatile comes with a performance penalty the can be substantial.
Also, since declarations involving volatile can be difficult to decipher the want to use CDECL (1).