You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 4 Next »

As described in-depth in [DCL34-C. Use volatile for data that cannot be cached], a volatile-qualified variable "shall be evaluated strictly according to the rules of the abstract machine" [[ISO/IEC 9899:1999]].  In other words, the volatile qualifier is used to instruct the compiler to not make caching optimizations about a variable.

However, as demonstrated in [[Eide and Regehr]], all tested compilers generated some percentage of incorrect compiled code with regards to volatile accesses.  Therefore, it is necessary to know how your compiler behaves when the standard volatile behavior is required.  There is also a workaround that eliminates some or all of these errors [[Eide and Regehr]].

Incorrectly-compiled Code Example

As demonstrated in [[Eide and Regehr]], the following code example compiles incorrectly using GCC version 4.3.0 for IA32 and the -Os optimization flag:

const volatile int x;
volatile int y;
void foo(void) {
    for(y = 0; y < 10; y++) {
        int z = x;
    }
}

Because the variable x is volatile-qualified, it should be accessed ten times in this program.  However, as shown in the compiled object code, it is only accessed once due to a loop-hoisting optimization [[Eide and Regehr]]:

foo:
    movl $0, y
    movl x, %eax
    jmp .L2
.L3:
    movl y, %eax
    incl %eax
    movl %eax, y
.L2:
    movl y, %eax
    cmpl $10, %eax
    jg .L3
    ret

Should x represent a hardware register or some other memory-mapped device that has side effects when accessed, the previous miscompiled code example may produce unexpected behavior.

References

[[Eide and Regehr]] "Volatiles Are Miscompiled, and What to Do about It"
[[ISO/IEC 9899:1999]] Section 6.7.3, "Type qualifiers"

  • No labels