The trap of volatile

Source: Internet
Author: User

for the volatile keyword, most of the C language tutorials are a stroke of the same, and did not do much in-depth analysis, so here is a simple collation of somePrecautions for use of volatile. In fact, the syntax is the same as volatile and const, but if the const is wrong, there will be littleproblem, and volatile is wrong, the consequences can be serious. Therefore, in the use of volatile suggested that everyone should try to stabilize, less use of the actualgrip skills.  First look at the difference between the following two definitions:
1 Char volatile reg;

In this line of code, Reg is a pointer type that stores a pointer to the unsigned char type. The volatile modifier is the Reg variable, which is the pointer

The variable is volatile, but the Unsigne char content pointed to by the pointer is not volatile. In the actual use of the compiler code in the pointer variable reg

The operation itself will not be optimized, but the content referred to by Reg "*reg" will be treated as no-volatile content, and the operation of "*reg" will be optimized.

Usually this is used in a shared pointer variable, that is, the pointer variable may be interrupted function modification, defined as volatile after the compiler

Each time a pointer variable value is taken, it is loaded from memory, so that even if the variable has been modified by another program, the current function can be modified

Value (otherwise, it is usually only placed in the register once the function is started, and the copy in the register is used later).

1     volatile Char *reg;

In this line of code, the volatile modifier is what the pointer refers to, so this defines a pointer to the unsigned char type, and this pointer points to the

is a volatile object, but the pointer variable itself is not volatile. If the pointer variable reg itself is computed or assigned operations, it is possible to be programmed

Compiler-Optimized. However, the *reg reference to the content referred to by Reg prohibits compiler optimizations. Because this pointer refers to a volatile object,

The compiler must ensure that operations on *reg are not optimized. Typically in driver development, the definition of a hardware register pointer should take this form.

1     volatile Char volatile Reg

The defined pointer itself is a volatile variable and points to the volatile data content.

---------------------------------------------"Split Line"----------------------------------------------------

The combination of volatile and const

 Literally, volatile and const seem to be two opposing properties of an object and are mutually exclusive. But in fact, the two are likely to work together to modify the same

of the object. Take a look at this line statement below.

    extern Const volatile int Rt_clock;

This is a common statement in the RTOs kernel: Rt_clock usually refers to the system clock, he is often updated by the clock interrupt, so he is volatile

, variable. So let the compiler take a value from the memory every time you use it. While Rt_clock usually has only one writer (clock interrupt), the use of other places

is usually read-only, so declare it as const, which means that the variable should not be modified here. So volatile and const are two things that are not contradictory, and a

It is also meaningful for objects to have both of these properties.

Note: The above example should be aware that declarations and definitions are used as const, and should be defined in the interrupt function that requires reading and writing Rt_clock variables.

// in the interrupt function that needs to read and write the Rt_clock variable, define the following Char volatile reg;
// This can be stated in the Declaration header file provided to the user Const volatile int Rt_clock;

Look at one more example.
volatile struct const DVP = DEVADDR;

The volatile and const are actually decorated with two different objects: the volatile modifier is the type that the pointer DVP points to as a struct devregs

Data structure, which corresponds to the hardware registers of the device, so it is variable and cannot be optimized, whereas the latter const modifies the pointer variable DVP. Should be a hard

The part register address is a constant, so this pointer variable is defined as const and cannot be modified.

---------------------------------------------"Split Line"----------------------------------------------------

Dangerous volatile usage Example: struct member defined as volatile Examine the structure type definition of a device hardware register:
struct Deveregs {   shortvolatile  CSR;     Short Const volatile data;};

Our intention is to declare a hardware register group of a device with a 16bit CSR register, which can be written by the program to the device

The control word can also be set by the hardware device to reflect its working state. There is also a 16bit data register, which will only have hardware settings

Read in by the program.

There seems to be no problem with the definition of the structure, and it fits the actual situation. But what happens when you execute code like the following.

struct const DVP = DEVADDR;
 while 0 ) {     //NULL wait tilldone    ;   }

What will the compiler do with a non-volatile struct pointer that accesses a struct member that is defined as volatile? The answer is: undefined!

The C99 standard does not prescribe the behavior of the compiler in this case, and it is possible for the compiler to properly handle Dvp->car as a volatile variable to make the program

Run normally, it is also possible to treat DVP->CSR as a normal non-volatile variable, which is optimized in while to only the beginning of the value once, and later

Each subsequent loop will always use the first fetch value and no longer read from the hardware register, so that the code above is likely to die in a loop.

If you use a volatile pointer to point to a non-volatile object, such as assigning a non-volatile struct to a volatile pointer,In this way, the use of a volatile pointer to a struct is considered volatile by the compiler, and the original object is not declared volatile. In turn, however,If you assign the address of a volatile object to a non_volatile normal variable, the result of accessing the volatile object through this pointer is undefined, which isdangerous.

So for the code in this example, we should change to this:

struct devregs{    short  CSR;      Short data;}; volatile struct const DVP = Devadde;

This allows us to guarantee that the DVP pointer accesses the struct members when it is volatile to handle them.

Example: struct type defined as volatile

Examine the following code:

volatile struct devregs{...    } Dev1; struct devregs dev2;

The purpose of the author may be to define a volatile struct type and, by the way, define a volatile structural body variable,

Therefore, a dev2 is defined. However the DEV2 variable defined in the second time is actually non-volatile! Because actually in the definition structure

Body type, the keyword volatile modifies a struct that dev1 this variable rather than the struct DEVREGSS type.

So this code should be written like this:

volatile struct devres{... }devregs_t;devregs_t Dev1; devregs_t Dev2;

This allows us to get two volatile structural variables.

Example: multiple indirect pointer references

Examine the following code:

struct bd{     int state ;   Char* Data_buff;} ;
struct devregs{    int  CSR;     struct bd* tx_bd;     struct bd* rx_bd;}; volatile struct const DVP = DEVADDR;DVP->tx_bd->state = ready ;  while 0 ){  ;}

Such code is commonly used in sending buffer to some DMA devices. Typically, the state of these buffer descriptor (BD) is performed by the hardwareThe settings have been told that the software buffer is finished sending or receiving. Note, however, that the operation on Dvp->ta_bd->state in the above code is actually non-volatile, it is possible for the compiler to optimize its read to cause it to fall back into a dead loop. since the DVP already defines a volatile pointer, only the DEVREGS structure to which it points is a range of volatile object,is that a pointer to the volatile data that is declared by the DVP can guarantee that the TX_BD within the volatile object it refers to is volatilevariable, but it is not guaranteed that the data referred to by this pointer variable is volatile (because the pointer is not declared as a pointer to volatile). to make the above code work as defined below
struct devregs{    int  CSR;     volatile struct bd* tx_bd;     volatile sturct bd* rx_bd;};

This ensures that the handling of State members is volatile. But the surest and clearest way to do this is to

volatile struct const DVP = devaddr; volatile struct bd* tx_bd = dvp->tx_bd;tx_bd->state = Ready;whlie ((tx_bd0) {   ;}

In this way, the code can guarantee the variability of the data structure, even if the data structure is not well defined. And it's good for future maintenance.

: Because you can see from the code that the data access is guaranteed to be volatile.

Example: Exactly which volatile may be invalid

In the first few examples, it may be better to look at this example when you feel like you've already figured it out.

struct hw_bd{.....      volatile Char volatile buffer;}; struct hw_bd* bdp;......bdp//1//2

What is the result of the code above labeled 1 and 2 which is actually accessing the volatile object and which is the undefined.

The answer is that 2 is volatile and 1 is undefined. Look at this example data structure

(Non-volatile)

bdp->+---------+

| |

| ...  ...    |

| |

+---------+ (volatile)

| Buffer |-->+----------+

+---------+     /               /

/               /

/               /

+----------+

/buffer/

+----------+

/               /

/               /

+----------+

The buffer member itself is accessed through a non-volatile clock BDP, as defined by the C99 standard, which belongs to

Undefined, so access to the Bdp->buffer compiler is not necessarily guaranteed to be volatile, although the buffer

itself may not be a volatile variable, but the buffer member is a pointer to a volatile object. Therefore, the buffer

The access compiler for the object to which the member points is guaranteed to be volatile, so the bdp->buffer is volatile.

So, seemingly simple volatile keyword, use up or have a lot of attention.

The trap of volatile

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.