Forcing a variable to be read

The nested project I'm working on requires reading a specific memory location, but the value of that memory location is not required. I am currently reading a mutable variable into a dummy variable, as in foo1() below, but I'm interested in the method in foo2() .

 void foo1(void) { volatile uint32_t *a = (volatile uint32_t *)0xdeadbeef; volatile uint32_t discard = *a; } void foo2(void) { volatile uint32_t *a = (volatile uint32_t *)0xdeadbeef; *a; } 

See disassembly (compiled with gcc 4.7.2 and -O3):

  foo1: movl 0xdeadbeef, %eax movl %eax, -0x4(%rsp) ret foo2: movl 0xdeadbeef, %eax ret 

The method in foo2() seems to work, but I want to know if it is guaranteed to work and is not a side effect of the compiler version and the optimizations I use.

+6
source share
3 answers

The volatile keyword tells the compiler that an object can change outside the scope of a regular (that is, visible to the compiler) program stream. Therefore, the compiler performs this access in general . The last sentence relates to how access is performed, for example. byte read, unaligned read, etc.

Moreover, the compiler must perform all calls to such objects in the order specified by the program stream. Please note, however, that it can freely reorder calls to non-volatile objects, and the underlying equipment may think differently (the compiler may not know this).

The compiler can still optimize access to volatile objects that exist and are changed only in visible code. This is true for local variables where the address is not accepted (there may be other situations), since they cannot be reached outside the scope. This is not true for the pointers you use, because the compiler does not know about the object they are pointing to.

To discard the result of an expression without warning the compiler, simply add it to void :

 volatile uint32_t *vi = ...; (void)*vi; // this still might be optimized if vi is local 

(If the target is read-only, add const .)

For more information on volatile access, see the gcc documentation. An implementation conforming to the C standard should provide this information.

Also note that the underlying hardware can still change the access order if the memory area does not use a strictly ordered / non-cached access policy. This is typical of peripheral registers with memory mapping. If a cache / MMU is used, it may be necessary to configure areas.

+2
source

It is standard in C, but not C ++. See: https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Volatiles.html

BUT, you certainly do not need to do volatile write in discard . They will probably be compiled in the same way as foo2:

  • use foo1, but remove the volatile qualifier with discard ; or
  • use foo2, but use !*a or * a + 0 instead of *a . Access to the value must be obtained in order to evaluate the expression, even in C ++
+2
source

There is no guarantee that dereferencing a volatile object causes read access, see ISO 9899: 2011 Β§6.7.3 ΒΆ7:

An object that has a mutable type can be modified in ways that are unknown to the implementation or that have other unknown side effects. Therefore, any expression relating to such an object must be evaluated strictly in accordance with the rules of the abstract machine, as described in 5.1.2.3. In addition, at each point in the sequence, the value stored last in the object must match the value prescribed by the abstract machine, with the exception of those modified by unknown factors mentioned earlier. 134) What constitutes access to an object that has a type with variable qualifications is determined by the implementation.

134) A volatile declaration can be used to describe an object corresponding to an I / O port with memory or an object accessed by the asynchronous interrupt function. Actions on declared objects should not be "optimized" by the implementation or reordered, unless permitted by the rules for evaluating expressions.

In practice, implementations of the C programming language are usually defined unary * to create access to the object, thereby ensuring that *a causes read access to the variable a .

+1
source

All Articles