Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Force read of volatile variable

An embedded project I'm working on requires reading a specific location in memory, but the value of that memory location is not needed. Currently I am reading the volatile variable into a dummy variable as in foo1() below, but I am curious about 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 the dissassembly (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 isn't a side effect of the compiler version and optimizations I am using.

like image 330
Tim Avatar asked Dec 30 '15 01:12

Tim


People also ask

What happens when you write to a volatile variable?

When we write to a volatile variable, it creates a happens-before relationship with each subsequent read of that same variable. So any memory writes that have been done until that volatile variable write, will subsequently be visible to any statements that follow the read of that volatile variable.

What is the use of volatile keyword in Java?

The volatile keyword is useful in two multi-threading scenarios: When only one thread writes to the volatile variable and other threads read its value. Thus, the reading threads see the latest value of the variable. When multiple threads are writing to a shared variable such that the operation is atomic.

What is a volatile global variable?

1) Global variables modified by an interrupt service routine outside the scope: For example, a global variable can represent a data port (usually global pointer referred as memory mapped IO) which will be updated dynamically. The code reading data port must be declared as volatile in order to fetch latest data available at the port.

What is the field to read in the volatile class?

The field to read. The reference to T that was read. This reference is the latest written by any processor in the computer, regardless of the number of processors or the state of processor cache. For more information, see the Volatile class. Returns a 64-bit unsigned value, loaded as an atomic operation.


2 Answers

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

BUT, you certainly don't need to do the volatile write to discard. These will probably all compile to the same as foo2:

  • use foo1, but remove the volatile qualifier from discard; or
  • use foo2, but use !*a or *a + 0 instead of *a. The value must be accessed in order to evaluate the expression, even in C++
like image 40
Matt Timmermans Avatar answered Oct 08 '22 22:10

Matt Timmermans


The keyword volatile tells the compiler an object might change outside the scope of the normal (i.e. visible by the compiler) program flow. Therefore, the compiler performs this access in general. The last sentence refers to how the access is performed, e.g. byte-read, unaligned reads, etc.

Futhermore, the compiler must execute all accesses to such objects in the order given by the program flow. Note, however, that it may reorder accesses to non-volatile objects freely and the underlying hardware might think different, too (the compiler might not know that).

The compiler might still optimize accesses to volatile objects which exist and are modified only in the visible code. This is true for local variables where the address is not taken (there might be other situations), as these cannot be reached outside the scope. For the pointers you use, this is not true, as the compiler does not know about the object they point to.

To drop the result of an expression without compiler warning, just cast 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.)

See the gcc documentation for details on volatile accesses. An implementation which complies to the C standard has to provide this information.

Also note that the underlying hardware still might reorder the accesses, unless the memory area uses a strictly ordered/non-cached access policy. This is typical for memory-mapped peripheral registers. If a cache/MMU is used, the areas might have to be set up accordingly.

like image 186
too honest for this site Avatar answered Oct 08 '22 22:10

too honest for this site