C language volatile keyword

Source: Internet
Author: User

The volatile reminder compiler can change the variables that are defined later, so the compiled program reads the data directly from the variable address each time it needs to store or read the variable. Without the volatile keyword, the compiler might optimize reading and storage, may temporarily use the value in the register, and if the variable was updated by another program, there would be an inconsistency. The following examples illustrate. In DSP development, it is often necessary to wait for an event to be triggered, so the program is often written like this:

 Short Flag; void Test () {do1 ();  while (flag==0);d O2 ();}

    This program waits for the value of the memory variable flag to change to 1 (suspect here is 0, a little doubt) before running Do2 (). The value of the variable flag is changed by another program, which may be a hardware interrupt service program. For example, if a button is pressed, the DSP will be interrupted, the key in the interrupt program to modify flag 1, so that the above program can continue to run. However, the compiler does not know that the value of flag will be modified by another program, so when it is optimized, the value of flag may be read into a register first, and then wait for that register to become 1. If such optimizations are unfortunate, then the while loop becomes a dead loop because the contents of the register cannot be modified by the Interrupt service program. In order for the program to read the value of the TRUE flag variable every time, it needs to be defined as follows:
volatile short flag;
    It is important to note that no volatile is possible, but it may not work properly after modifying the compiler's optimization level. As a result, the debug version is normal, but the release version is not a normal issue. So for security reasons, just wait for another program to modify a variable, plus the volatile keyword.

volatile is meant to be "variable"
      Because access registers are faster than RAM, compilers generally reduce access to external RAM optimizations. For example:

Static int i=0; int Main (void) {...  while (1) {if  (i) do_something ();}} /*  */void isr_2(void) {i=1;}


The intent of the program is to call the Do_something function in main when the isr_2 interrupt is generated, but because the compiler determines that I is not modified in the main function, it may only perform a single read from I to a register. Then each time the if judgment uses only the "I copy" inside the register, causing the do_something to never be called. If the variable is modified with a volatile modifier, the compiler guarantees that read and write operations on this variable will not be optimized (definitely executed). I should also explain this in this example.
Generally, volatile is used in several places:
1, the change in the Interrupt service program for other programs to detect variables need to add volatile;
2, multi-tasking environment to share the logo should be added volatile;
3, Memory mapping hardware register usually also add volatile description, because each time it read and write may be different meanings;
In addition, these situations often have to consider the integrity of the data at the same time (the correlation of several signs read half interrupted rewrite), in 1 can be achieved by the shutdown interrupt, 2 can prohibit task scheduling, 3 of the hardware can only rely on good design.
Second, the meaning of volatile
Volatile is always about optimization, and the compiler has a technique calledData Flow Analysis, where variables in the parser are assigned, where they are used, where they are invalidated, analysis results can be used for constant merging, constant propagation and other optimizations, and further die code elimination. But sometimes these optimizations are not required by the program, you can use the volatile keyword to prohibit these optimizations, the literal meaning of volatile is variable, it has the following role:
1 The volatile variable is not cached in a register between two operations. In multi-tasking, interrupts, and even setjmp environments, variables can be changed by other programs, and the compiler cannot know for sure, and volatile is telling the compiler this is the case.
2 Do not do constant merging, constant propagation and other optimizations, so like the following code:
volatile int i = 1;
if (i > 0) ...
The IF condition is not treated as unconditional true.
3 reading and writing to volatile variables is not optimized. If you assign a value to a variable but it doesn't work, the compiler can often omit that assignment, but the processing of memory Mapped IO cannot be optimized.
Some people said that volatile can guarantee the atomic nature of memory operations, this is not accurate, one, x86 need lock prefix to ensure atomicity under the SMP, and second, RISC can not directly operate on the memory, to ensure that the atomicity of other methods, such as Atomic_inc.
For Jiffies, it has been declared as a volatile variable, and I think it is possible to use jiffies++ directly, and there is no need to use that complex form, because that does not guarantee atomicity.
You may not know that in Pentium and subsequent CPUs, the following two sets of instructions

%%

function the same, but an instruction is not as fast as three instructions.
Third, compiler optimization →C keyword volatile→memory break descriptor zz

    "Memory" is special and may be the hardest part of inline compilation. To explain it clearly, first introduce the compiler's optimization knowledge, and then see the C keyword volatile. Finally, look at the descriptor.  
1, compiler optimization introduction  
      memory access speed is far less than CPU processing speed, in order to improve the overall performance of the machine, hardware cache caches are introduced on the hardware to speed up access to memory. In addition, the execution of instructions in the modern CPU is not necessarily executed in sequence, and no correlation instruction can be executed in order to make full use of the CPU's instruction pipeline and improve the execution speed. These are hardware-level optimizations. Look at software-level optimizations: One is optimized by programmers while writing code, and the other is optimized by the compiler. Compiler optimizations are commonly used in the following ways: caches memory variables to registers, and adjusts instruction sequences to take full advantage of CPU instruction pipelining, often by reordering read and write instructions. These optimizations are transparent and efficient when the optimizes for conventional memory. The solution to the problem caused by compiler optimizations or hardware reordering is to set the memory barrier between actions that must be performed in a particular order from the point of view of the hardware (or other processor), and Linux provides a macro to solve the compiler's order of execution issues.  
void Barrier (void)  
      This function notifies the compiler to insert a memory barrier, but is not valid for the hardware, and the compiled code will store all the modified values in the current CPU register in memory And then re-read from memory when this data is needed.  
2, c keyword volatile 
     c keyword volatile (note that it is used to modify variables rather than the __volatile__ described above) ) indicates that the value of a variable may be changed externally, so access to these variables cannot be cached to the register, which needs to be re-accessed each time it is used. This keyword is often used in multi-threaded environments, because when writing multithreaded programs, the same variable can be modified by multiple threads, and the program synchronizes threads through that variable, for example:  

int* intsignal=reinterpret_cast<int*>*intsignal=2while (*intsignal!=1) sleep (return0


The thread starts with intsignal set to 2, and then loops until intsignal exits 1 o'clock. It is obvious that the value of intsignal must be changed externally, otherwise the thread will not exit. However, the thread does not exit when it is actually running, even if it is externally changing its value to 1, look at the corresponding pseudo-assembly code to understand:

if (ax!=1Goto


For the C compiler, it does not know that this value will be modified by another thread. Naturally, it caches it in the register. Remember, the C compiler does not have a threading concept! This is where the use of volatile is needed. Volatile is intended to mean that this value may be changed outside the current thread. That is, we want to add the volatile keyword in front of the intsignal in ThreadFunc, when the compiler knows that the value of the variable changes externally, so each time the variable is accessed it is reread and the loop becomes as shown in the following pseudo-code:

if (ax!=1Goto


3. Memory
With the knowledge above it is not difficult to understand the memory modification descriptor, the memory descriptor tells GCC:
1) do not reorder the inline assembly instruction with the preceding instruction, that is, before executing the inline assembly code, the instructions before it are executed
2) do not cache variables to registers, because this code may use memory variables, and these memory variables will be changed in an unpredictable way, so gcc insert the necessary code to cache the value of the variables cached to the register back to memory, if the subsequent access to these variables, need to re-access memory.
If the assembly instruction modifies the memory, but GCC itself is not aware of, because in the output section is not described, it is necessary to add "memory" in the modification Description section, to tell the GCC memory has been modified, when GCC learned this information, will be before this command, Inserting the necessary instructions will first write back the values of the variables in the cache to the register, and then re-read them if they are to be used later.
This can also be achieved with "volatile", but instead of adding the keyword before each variable, it is easier to use "memory".

C language volatile keyword

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.