You are on page 1of 9

@Articles on Volatile

In computer programming, particularly in the C, C++, C#, and Java programming languages,a variable or object declared with the volatile keyword usually has special properties related to optimization and/or threading. Generally speaking, the volatile keyword is intended to prevent the (pseudo)compiler from applying any optimizations on the code that assume values of variables cannot change "on their own." A wikipedia example of volatile : In this example, the code sets the value stored in foo to 0. It then starts to poll that value repeatedly until it changes to 255:

static int foo; void bar(void) { foo = 0; while (foo != 255) ; }


An optimizing compiler will notice that no other code can possibly change the value stored in foo, and will assume that it will remain equal to 0 at all times. The compiler will therefore replace the function body with an infinite loop similar to this:

void bar_optimized(void) { foo = 0; while (true) ; }


However, foo might represent a location that can be changed by other elements of the computer system at any time, such as a hardware register of a device connected to the CPU. The above code would never detect such a change; without the volatile keyword, the compiler assumes that the current program is the only part of the system that could change the value (which is by far the most common situation).
1

To prevent the compiler from optimizing code as above, the volatile keyword is used: static volatile int foo; void bar (void) { foo = 0; while (foo != 255) ; } With this modification the loop condition will not be optimized away, and the system will detect the change when it occurs. An article from www.linuxforu.com Demystifying the Volatile Keyword in C : Most programmers dont understand the meaning and significance of the volatile keyword. So lets explore that in this months Joy of Programming. One of my favourite interview questions for novice programmers is: What is the use of the volatile keyword? For experienced programmers, I ask: Can we qualify a variable as both const and volatileif so, what is its meaning? I bet most of you dont know the answer, right? The keyword volatile is to do with compiler optimisation. Consider the following code:

long *timer = 0X0000ABCD; // assume that at location 0x0000ABCD the current time is available long curr_time = *timer; // initialize curr_time to value from timer // wait in while for 1 sec (i.e. 1000 millisec) while( (curr_time - *timer) < 1000 ) { curr_time = *timer; // update current time } print_time(curr_time); // this function prints the current time from the // passed long variable

@Articles on Volatile

Usually, hardware has a timer that can be accessed from a memory location. Here, assume that its 00000ABCD and is accessed using a long * variable timer (in the UNIX tradition, time can be represented as a long variable and increments are done in milliseconds). The loop is meant to wait one second (or 1,000 milliseconds) by repeatedly updating curr_time with the new value from the timer. After a one second delay, the program prints the new time. Looks fine, right? However, from the compiler point of view, what the loop does is stupidit repeatedly assigns curr_time with *timer, which is equivalent to doing it once outside the loop. Also, the variable timer is de-referenced repeatedly in the loopwhen it is enough to do it once. So, to make the code more efficient (i.e., to optimise it), it may modify loop code as follows:

curr_time = *timer; // update current time long temp_time = *timer; while( (curr_time - temp_timer) < 1000 ) nothing here */ }

/* do

As you can see, the result of this transformation is disastrous: the loop will never terminate because neither is curr_time updated nor is the timer dereferenced repeatedly to get new (updated time) values. What we need is a way to tell the compiler not to play around with such variables by declaring them volatile, as in:

volatile long * timer = 0x0000ABCD; volatile curr_time = *timer;


Now, the compiler will not do any optimisation on these variables. This, essentially, is the meaning of the volatile keyword: It declares the variables as asynchronous variables, i.e., variables that are not-modifiedsequentially. Implicitly, all variables that are not declared volatile are synchronous variables. How about qualifying a variable as both const and volatile? As we know, when we declare a variable as const, we mean its a read-only variable once we initialise it, we will not change it again, and will only read its value. Here is a modified version of the example:

long * const timer = 0x0000ABCD; // rest of the code as it was before..


3

We will never change the address of a timer, so we can put it as a const variable. Now, remember what we did to declare the timer as volatile:

volatile long * timer = 0x0000ABCD;


We can now combine const and volatile together:

volatile long * const timer = 0x0000ABCD;


It reads as follows: the timer is a const pointer to a long volatile variable. In plain English, it means that the timer is a variable that I will not change; it points to a value that can be changed without the knowledge of the compiler! Review of the above article :
Wow this is a really good article. I m glad to have read it. I m looking forward for more of your articles. I really enjoyed reading it. Its good to know that there is much more knowledge to gain on this topic. Just keep posting your good work and keep enlightening your readers. Thank you..

ok here is the comment made by others about logical flaw in ur explanation: 1 person commented: The above link [i gave this link] doesnt answer the question that he asked in the first place. I cant believe that he is writing a book. Well when people like Yashwant Kanitkar can write a book am sure anyone else can. His question was For experienced programmers, I ask: Can we qualify a variable as both const and volatileif so, what is its meaning? I bet most of you dont know the answer, right? And he ends up answering like this: How about qualifying a variable as both const and volatile? As we know, when we declare a variable as const, we mean its a read-only variable once we initialise it, we will not change it again, and will only read its value. Here is a modified version of the example:

long * const timer = 00000ABCD; // rest of the code as it was before..


We will never change the address of a timer, so we can put it as a const variable. Now, remember what we did to declare the timer as volatile:

volatile long * timer = 00000ABCD;

@Articles on Volatile

We can now combine const and volatile together:

volatile long * const timer = 00000ABCD;


But he forgot that he is not using const and volatile on the same variable. In his example what is being pointed to is volatile while what he is using to point is const. That is very different from the question that he asked. Here u r declaring timer as const pointer to long; as its a const pointer, timer cant be changed to point to some other location in the program but the pointed to value can be changed..isnt it?

Your question is misleading, With the question , everyone will think that how a same variable can be volatile and const. But you are making the pointer as constant and value as volatile.

An article by Nigel Jones from www.netrino.com How to Use C's volatile Keyword : Proper use of volatile

A variable should be declared volatile whenever its value could change unexpectedly. In practice, only three types of variables could change: 1. Memory-mapped peripheral registers 2. Global variables modified by an interrupt service routine 3. Global variables accessed by multiple tasks within a multi-threaded application We'll talk about each of these cases in the sections that follow.

Peripheral registers

Embedded systems contain real hardware, usually with sophisticated peripherals. These peripherals contain registers whose values may change asynchronously to the program flow. As a very simple example, consider an 8-bit status register that is memory mapped at address 0x1234. It is required that you poll the status register until it becomes non-zero. The naive and incorrect implementation is as follows:

uint8_t * pReg = (uint8_t *) 0x1234; // Wait for register to become non-zero while (*pReg == 0) { // Do something else

}
5

This will almost certainly fail as soon as you turn compiler optimization on, since the compiler will generate assembly language that looks something like this:

mov ptr, #0x1234 mov a, ptr loop: bz loop


The rationale of the optimizer is quite simple: having already read the variable's value into the accumulator (on the second line of assembly), there is no need to reread it, since the value will always be the same. Thus, in the third line, we end up with an infinite loop. To force the compiler to do what we want, we modify the declaration to:

uint8_t volatile * pReg = (uint8_t volatile *) 0x1234;


The assembly language now looks like this:

mov ptr, #0x1234 loop: mov a, ptr bz loop


The desired behavior is achieved. Subtler problems tend to arise with registers that have special properties. For instance, a lot of peripherals contain registers that are cleared simply by reading them. Extra (or fewer) reads than you are intending can cause quite unexpected results in these cases. Interrupt service routines

Interrupt service routines often set variables that are tested in mainline code. For example, a serial port interrupt may test each received character to see if it is an ETX character (presumably signifying the end of a message). If the character is an ETX, the ISR might set a global flag. An incorrect implementation of this might be:

int etx_rcvd = FALSE; void main() { ... while (!ext_rcvd) { // Wait } ... }

@Articles on Volatile

interrupt void rx_isr(void) { ... if (ETX == rx_char) { etx_rcvd = TRUE; } ... }


With compiler optimization turned off, this code might work. However, any half decent optimizer will "break" the code. The problem is that the compiler has no idea that etx_rcvd can be changed within an ISR. As far as the compiler is concerned, the expression !ext_rcvd is always true, and, therefore, you can never exit the while loop. Consequently, all the code after the while loop may simply be removed by the optimizer. If you are lucky, your compiler will warn you about this. If you are unlucky (or you haven't yet learned to take compiler warnings seriously), your code will fail miserably. Naturally, the blame will be placed on a "lousy optimizer." The solution is to declare the variable etx_rcvd to be volatile. Then all of your problems (well, some of them anyway) will disappear. Multi-threaded applications

Despite the presence of queues, pipes, and other scheduler-aware communications mechanisms in real-time operating systems, it is still fairly common for two tasks to exchange information via a shared memory location (that is, a global). Even as you add a preemptive scheduler to your code, your compiler has no idea what a context switch is or when one might occur. Thus, another task modifying a shared global is conceptually identical to the problem of interrupt service routines discussed previously. So all shared global variables should be declared volatile. For example, this is asking for trouble:

int cntr; void task1(void) { cntr = 0; while (cntr == 0) { sleep(1); } ... } void task2(void)
7

{ ... cntr++; sleep(10); ... }


This code will likely fail once the compiler's optimizer is enabled. Declaring cntr to be volatile is the proper way to solve the problem.

o Final thoughts Some compilers allow you to implicitly declare all variables as volatile. Resist this temptation, since it is essentially a substitute for thought. It also leads to potentially less efficient code. Also, resist the temptation to blame the optimizer or turn it off. Modern optimizers are so good that I cannot remember the last time I came across an optimization bug. In contrast, I come across failures by programmers to use volatile with depressing frequency. If you are given a piece of flaky code to "fix," perform a grep for volatile. If grep comes up empty, the examples given here are probably good places to start looking for problems.

So, can const and volatile be used together ?


const is used with a datatype declaration or definition to specify an

unchanging value and volatile specifies a variable whose value may be changed by processes outside the current program . One example of a volatile object might be a buffer used to exchange data with an external device: check_iobuf(void) { volatile int iobuf; int val; while (iobuf == 0) { } val = iobuf; iobuf = 0; return(val); } if iobuf had not been declared volatile, the compiler would notice that nothing

@Articles on Volatile happens inside the loop and thus eliminate the loop. Here, const and volatile can be used together : o An input only buffer for an external device could be declared as const volatile (or volatile const, order is not important) to make sure the compiler knows that the variable should not be changed (because it is input-only) and that its value may be altered by processes other than the current program.

You might also like