Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can compiler sometimes cache variable declared as volatile

From what I know, the compiler never optimizes a variable that is declared as volatile. However, I have an array declared like this.

volatile long array[8];

And different threads read and write to it. An element of the array is only modified by one of the threads and read by any other thread. However, in certain situations I've noticed that even if I modify an element from a thread, the thread reading it does not notice the change. It keeps on reading the same old value, as if compiler has cached it somewhere. But compiler in principal should not cache a volatile variable, right? So how come this is happening.

NOTE: I am not using volatile for thread synchronization, so please stop giving me answers such as use a lock or an atomic variable. I know the difference between volatile, atomic variables and mutexes. Also note that the architecture is x86 which has proactive cache coherence. Also I read the variable for long enough after it is supposedly modified by the other thread. Even after a long time, the reading thread can't see the modified value.

like image 853
pythonic Avatar asked Oct 03 '12 14:10

pythonic


2 Answers

C

What volatile does:

  • Guarantees an up-to-date value in the variable, if the variable is modified from an external source (a hardware register, an interrupt, a different thread, a callback function etc).
  • Blocks all optimizations of read/write access to the variable.
  • Prevent dangerous optimization bugs that can happen to variables shared between several threads/interrupts/callback functions, when the compiler does not realize that the thread/interrupt/callback is called by the program. (This is particularly common among various questionable embedded system compilers, and when you get this bug it is very hard to track down.)

What volatile does not:

  • It does not guarantee atomic access or any form of thread-safety.
  • It cannot be used instead of a mutex/semaphore/guard/critical section. It cannot be used for thread synchronization.

What volatile may or may not do:

  • It may or may not be implemented by the compiler to provide a memory barrier, to protect against instruction cache/instruction pipe/instruction re-ordering issues in a multi-core environment. You should never assume that volatile does this for you, unless the compiler documentation explicitly states that it does.
like image 106
Lundin Avatar answered Sep 18 '22 13:09

Lundin


With volatile you can only impose that a variable is re-read whenever you use its value. It doesn't guarantee that the different values/representations that are present on different levels of your architecture are consistent.

To have such gurantees you'd need the new utilities from C11 and C++1 concerning atomic access and memory barriers. Many compilers implement these already in terms of extension. E.g the gcc family (clang, icc, etc) have builtins starting with prefix __sync to implement these.

like image 29
Jens Gustedt Avatar answered Sep 20 '22 13:09

Jens Gustedt