Demystifying the volatile keyword

Following on from my earlier post about the restrict keyword, I’d like to try and dispell the myth around the volatile keyword. The meaning of volatile is a popular interview question, particularly for embedded development jobs and I’ve heard some programmers describe the properties of this keyword as if it had super powers.

The volatile keyword does a very simple job. When a variable is marked as volatile, the programmer is instructing the compiler not to cache this variable in a register but instead to read the value of the variable from memory each and every time the variable is used. That’s it – simple isn’t it?

To illustrate the use of the keyword, consider the following example:volatile int* vp = SOME_REGISTER_ADDRESS;
for(int i=0; i<100; i++)     foo(*vp);[/sourcecode] In this simple example, the pointer vp points to a volatile int. The value of this int is read from memory for each loop iteration. If volatile was not specified then it is likely that the compiler would generate optimized code which would read the value of the int once, temporarily store this in a register and then use the register copy during each iteration. Examples of where volatile is often used:

  • When accessing hardware registers via pointers. It is necessary for the generated code to always access the hardware registers value and never a potentially out of date copy.
  • When accessing a variable that is shared between two or more threads or between a thread and an ISR.

Common myths about the volatile keyword:

  • A volatile variable will never reside in cache memory – e.g. within the L2 cache of a processor. This is not true. In the case where the volatile variable is shared between two software threads, it is highly likely that the variable will exist in cached memory and the cache coherency policy will ensure that the threads will see the correct and up-to-date value of the variable in the event that the threads are running on seperate cores that don’t share the same cache. When the volatile variable refers to a hardware register, it is likely that the memory map of the system will be setup such that this register is not cacheable in the processor cache, but this is setup and managed by the appropriate device driver and is not something that is provided by the volatile keyword.

Thats’ it. So the next time you hear somebody waxing lyrical about the super powers of the volatile keyword, please feel empowered to enlighten them!

10 Responses to “Demystifying the volatile keyword”

  1. Igor Levicki says:

    Do you perhaps have any idea what the C++ standard says regarding whether the compiler is allowed to optimize away unreferenced local variable marked as volatile?

  2. Stephen Doyle says:

    Sorry, I don’t know for certain. I would suspect though that it is allowed to optimize away the unreferenced local variable. Volatile really only protects against optimizations that may affect the value of the variable. Since the value of unreferenced variables is not an issue, then everything should be ok if it is optimized away.

  3. Igor Levicki says:

    Yes but that local variable could be indirectly accessed (and thus its value changed) from inline assembler block — then what?

    It is clear that in such case optimizing the variable away would lead to a program crash because of a stack overflow.

    I just checked C++ Standard draft and it is pretty unclear on that. I believe that there should be a way to tell the compiler “do not optimize away unreferenced local variables”.

    What do you think?

  4. Stephen Doyle says:

    Ah – I hadn’t thought of indirectly accessing that from an inline assembler block. In this case I’m not sure that the volatile keyword adds any value.

    Have you observed a compiler optimizing away such a variable and resulting in a crash? I’m tempted to write a code snippet and see what some standard compilers do in this scenario – have you already done this?

  5. […] Demystifying the volatile keyword » Software Ramblings What is volatile keyword means and when to use it (tags: C++ Programming) […]

  6. Igor Levicki says:

    >>Have you observed a compiler optimizing away such a variable and resulting in a crash?

    Yes I did.

    >>I’m tempted to write a code snippet and see what some standard compilers do in this scenario – have you already done this?

    I tested it only with Intel C++ Compiler and it crashes so I submitted an issue with Intel Premier Support to get some clarification and so far I haven’t got anything except the confirmation that they have reproduced it.

    Let me save you some effort, here is the code snippet I used:

    #include

    #define ALIGN __declspec(align(16))

    void zealot(void)
    {
    ALIGN volatile float wkr[4096]; // 16384 bytes
    ALIGN volatile float wki[4096]; // 16384 bytes
    ALIGN volatile float ak0[4096]; // 16384 bytes
    ALIGN volatile float ak1[4096]; // 16384 bytes

    __asm {
    xor eax, eax
    mov edx, 16384
    lea esi, wkr // reference wkr
    lea edi, ak0 // reference ak0
    mov dword ptr [1024 + edi + edx], eax // ak1[256] = 0
    }
    }

    int main(void)
    {
    zealot();
    printf(“I am not a zealot!\n”);
    return 0;
    }

    Arrays wki and ak1 get optimized away because there is no explicit reference in the inline assembler block.

    In my opinion the original C/C++ standard is too vague on the volatile keyword definition. They do say that the compiler should not optimize if it is not sure that the variable cannot be changed from the outside but in this case “outside” really should mean “outside of the compiler generated code”, not “outside of the function”.

  7. seo blog says:

    This is a very interesting article – I have added your blgo to my favourrites, I really like it, keep up the good work!

  8. Hi I like your post “Demystifying the volatile keyword” so well that I like to ask you whether I should translate and linking back. Please give me an answer. Your Preiserh

  9. Stephen Doyle says:

    Hi Preiserh,

    Please feel free to translate this post. I’m glad that you found it useful.

    Steve

  10. Hey! Your Post “Demystifying the volatile keyword” is very interesting for me. Unfortunately my written English is not so good so I write in German: Dir, meinem liebsten, geh