The role of Volatilekeyword in C language

Source: Internet
Author: User

I. Preface

1. Description of Compiler optimizations:

Because memory access is far less than CPU processing speed, in order to improve the overall performance of the machine, hardware to introduce hardware cache caches, speed up the access to memory. In addition, the operation of the instruction in the modern CPU does not necessarily run in strict order, and no correlation instruction can run in sequence, in order to make full use of the command line of the CPU and improve the running speed. These are hardware-level optimizations. Then look at software-level optimizations: one that is optimized by the program ape when writing code, and one that is optimized by the compiler. compiler optimizations often use methods such as caching memory variables to registers, adjusting instruction sequences to take full advantage of CPU instruction pipelining, and, more commonly, ordering read-write instructions again. These optimizations are transparent and efficient when conventional memory is optimized. The solution to the problem caused by compiler optimizations or hardware sequencing is to set the memory barrier between actions that must be run in a particular order from the perspective of the hardware (or other processor), and Linux provides a macro that resolves the compiler's order of operations.

void Barrier (void)

This function notifies the compiler to insert a memory barrier, but the hardware is not valid, and the compiled code will store all the changed values in the current CPU register in memory, and then read the data again from memory.

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, further eliminating some code. But sometimes these optimizations are not required by the program, and these optimizations can be banned with Volatilekeyword.

Two. Volatile specific explanations:

1.volatile is meant to be "variable" because the access register is much faster than accessing the memory unit, the compiler generally makes the optimization of memory reduction, but it is possible to read dirty data. When a volatile declaration variable value is required , the system always reads the data from its memory again , even if the preceding instruction has just read the data from there. Precisely, in the case of a variable that is keyword declared, the compiler will no longer optimize the code that visits the variable, providing a stable access to a particular address, and assuming that valatile is not used, the compiler optimizes the declared statement. (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 whatever optimization

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. Assuming volatile, compiler is not allowed to do whatever optimization, thus guaranteeing the original intent of the program:
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.

Like what:

volatile char A;

a=0;

while (!a) {

Do some things;

}

DoOther ();

assuming no volatiledoother () will not be run

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

1> the variables that are altered in the interrupt service program for other programs to be detected are required to be volatile;

Like what:

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 infers that I is not changed in the main function, it may only run once to read from I to a register, Then each time if inference uses only the "I copy" inside the Register, which causes the dosomething to never be called. Assuming that the variable is modified with a volatile modifier, the compiler guarantees that read and write operations on this variable will not be optimized (definitely run). 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 the 3> memory map are usually also voliate, because each time it is read and written, it may not be allowed to be justified.

Like what:

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

int *output = (unsigned int *) 0xff800000;//defines a ioport;

int init (void)

{

int i;

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

*output = i;

}

}

After the compiler optimization, the compiler feels the front loop half a day is nonsense, the final result has no effect, because finally only the output of this pointer is assigned to 9, so the compiler finally give you compiled code results equivalent to:

int init (void)

{

*output = 9;

}

Let's say that your process of initializing this external device must be assigned to it in the same order as the code above, and obviously the optimization process is not going to achieve the goal. Conversely, if you do not repeat the operation on this port, but repeat the read operation, the result is the same, the compiler after optimization, perhaps your code for this address read operation only once. From a code point of view, however, no matter what the problem is. 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.

Like what:

volatile int *output= (volatile unsigned int *) 0xff800000;//defines a i/oport

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 in 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?

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

2) Can a pointer be volatile?

To be able, when a service subroutine fixes a pointer pointing to a buffer.

The essence of 5.volatile:

Optimization of the 1> compiler

Within this thread, when reading a variable, in order to improve the access speed, the compiler sometimes reads the variable into a register, and then, when the value of the variable is taken, the value is directly from the register, and when the value of the variable is changed in this line thread, the new value of the variable is copied to the register in order to remain consistent.

When a variable changes its value by another thread, the value of the register does not change, causing the value of the application to read and the actual variable value to be inconsistent.

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.

2>volatile should be interpreted as "direct access to the original memory address" is more appropriate, "variable" such an explanation 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, however, 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 such as the following:

Long Square (volatile int *ptr)

{

int A;

A = *ptr;

Return a * A;

}

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

The role of Volatilekeyword in C language

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.