The role of the volatile keyword in Linux

Source: Internet
Author: User
Tags volatile

I. Preface

1. Description of Compiler optimizations:

Due to the memory access speed is far less than the CPU processing speed, in order to improve the overall performance of the machine, the hardware to introduce hardware cache caches, 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 to cache memory variables to registers, adjust instruction sequence to take full advantage of CPU instruction pipelining, and often reorder read and write instructions. These optimizations are transparent and efficient when conventional memory is optimized. 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 stores all the modified values in the current CPU register in memory, which is then re-read from memory when needed.

2.volatile is always about optimization, the compiler has a technique called data 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 some code can be eliminated. However, sometimes these optimizations are not required by the program, and these optimizations can be prevented with the volatile keyword.

Two. Volatile explanation:

1.volatile is meant to be "variable" because the access register is much faster than accessing the memory unit, so the compiler will generally reduce access to memory optimization, but it is possible to read dirty data. When a volatile declaration variable value is required , the system always re-reads the data from the memory it is in , even if the preceding instruction has just read the data from that location. To be precise, a variable that is declared by the keyword is not optimized by the compiler to access the variable's code, which provides stable access to a particular address, and if valatile is not used, the compiler optimizes the statement being declared. (Simply put: volatile keywords affect the result of compiler compilation, the variable declared by the volatile variable can be changed at any time, the operation related to the variable, do not compile optimization, to avoid errors)

2. See two examples:

1> tell compiler not to do any optimizations.

For example, to send two instructions to an address:
int *ip = ...; Device Address
*ip = 1; First instruction
*ip = 2; A second instruction
The above program compiler may be optimized as follows:
int *ip = ...;
*ip = 2;
Results The first instruction is missing. In the case of volatile, compiler does not allow any optimizations to be made to ensure the program's original intent:
volatile int *ip = ...;
*ip = 1;
*ip = 2;
Even if you want to compiler optimization, it will not be two times the value of the statement into one. It can only do other optimizations.

2> Variables defined with volatile are changed outside of the program and must be read from memory each time, rather than reusing the backups placed in the cache or register.

For example:

volatile char A;

a=0;

while (!a) {

Do some things;

}

DoOther ();

if no volatiledoother () will not be executed

3. Here are a few scenarios for using volatile variables:

1> The variables modified in the Interrupt service program for other programs need to be volatile;

For example:

static int i=0;

int main (void)

{

...

while (1) {

if (i) dosomething ();

}

/* Interrupt Service routine. */

void isr_2 (void)

{

I=1;

}

The intent of the program is to call the DoSomething function in the main function 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 dosomething to never be called. If you add a variable with a volatile modifier, the compiler guarantees that read and write operations on this variable are not optimized (definitely). I should also explain this in this example.

2> the flags that are shared between tasks in a multi-tasking environment should be volatile

The hardware registers of 3> memory mappings are usually also voliate, because each time it is read and written it may have different meanings.

For example:

Suppose you want to initialize a device, one of the registers of this device is 0xff800000.

int *output = (unsigned int *) 0xff800000;//defines an IO port;

int init (void)

{

int i;

for (i=0;i< 10;i++) {

*output = i;

}

}

After compiler optimization, the compiler thinks the front loop is nonsense for half a day, and has no effect on the final result, because the output pointer is only assigned a value of 9, so the compiler finally gives you the result of compiling the compiled code:

int init (void)

{

*output = 9;

}

If the process of initializing this external device is to be assigned to it in the same order as the code above, it is clear that the optimization process is not going to achieve the goal. Conversely, if you do not write to this port repeatedly, but read the operation repeatedly, the result is the same, the compiler after optimization, perhaps your code for this address read operation only once. However, from a code point of view there is no problem. It is time to use volatile to notify the compiler that the variable is an unstable one, and do not optimize when encountering this variable.

For example:

volatile int *output= (volatile unsigned int *) 0xff800000;//defines an I/O port

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 of the ban task scheduling, 3 can only rely on the good hardware design.

4. Several questions

1) can a parameter be either const or volatile?

Yes, such as a read-only status register. It is volatile because it can be changed unexpectedly. It is const because the program should not attempt to modify it.

2) Can a pointer be volatile?

Yes, when a service subroutine fixes a pointer to a buffer.

The essence of 5.volatile:

Optimization of the 1> compiler

In this thread, when reading a variable, in order to improve the access speed, the compiler will sometimes read the variable into a register, and then, when the value of the variable is taken directly from the register, the value of the variable will be copied into the register at the same time when the value of the variable is changed in the thread, in order to maintain consistency.

When a variable changes its value by another thread, the value of the register does not change accordingly, resulting in inconsistencies between the value that the application reads and the actual variable value.

When the register changes values due to other threads, the value of the original variable does not change, resulting in inconsistencies between the values the application reads and the actual variable values.

The 2>volatile should be interpreted as "direct access to the original memory address," which is more appropriate, and the "variable" interpretation is a bit misleading.

6. What is wrong with the following function:

int square (volatile int *ptr)

{

return *ptr * *PTR;

}

The purpose of the program is to return the pointer *ptr to the square of the value, but since *ptr points to a volatile parameter, the compiler will produce code similar to the following:

int square (volatile int *ptr)

{

int A, B;

A = *ptr;

b = *ptr;

return a * b;

}

Because the values of the *ptr can be unexpectedly changed, A and B may be different. As a result, this code may return to the square value you expect! The correct code is as follows:

Long Square (volatile int *ptr)

{

int A;

A = *ptr;

Return a * A;

}

Note: Frequent use of volatile is likely to increase code size and reduce performance, so use volatile appropriately.

The Volatie variable will not have a relationship with the cache, only the memory.

The simple point is that the value is accessed from the inside before each operation.

There are volatie modified variables, each of which follows the following action:

value from inside Access ---> put register ----> Operation ----> write back to memory

Without Volatie modified variables, the operation may follow:

From the inside Access value---> put register----> First Action-----> second operation (at this point the value in the register is still operating) ...----> nth operation----> write back Memory

Give an example of the relationship between the two

int Volatie i; //global variable, which will be modified elsewhere

while (i)

{

Do_somethings ();

}

if I not be Volatie retouching, when while when the loop executes, another program executes concurrently. i = 0 , This loop still does not exit because each loop checks the value in the register.

If there is a volatie modification, then the loop ends, because each time the loop checks i , the memory will first read in register, this time I be assigned in other places 0 , the loop ends.

The role of the volatile keyword in Linux

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.