Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

`volatile` to sync variable between threads

I have a variable int foo that is accessed from two threads. Assuming I have no race-condition issues (access is protected by a mutex, all operations are atomic, or whatever other method to protect from race conditions), there is still the issue of "register caching" (for lack of a better name), where the compiler may assume that if the variable is read twice without being written in between, it is the same value, and so may "optimize" away things like:

while(foo) { // <-may be optimized to if(foo) while(1)
  do-something-that-doesn't-involve-foo;
}

or

if(foo) // becomes something like (my assembly is very rusty): mov ebx, [foo]; cmp ebx, 0; jz label;
  do-something-that-doesn't-involve-foo;
do-something-else-that-doesn't-involve-foo;
if(foo) // <-may be optimized to jz label2;
  do-something;

does marking foo as volatile solve this issue? Are changes from one thread guaranteed to reach the other thread?

If not, what other way is there to do this? I need a solution for Linux/Windows (possibly separate solutions), no C++11.

like image 269
Baruch Avatar asked Aug 08 '13 20:08

Baruch


2 Answers

What you need are memory barriers.

MemoryBarrier();

or

__sync_synchronize();

Edit: I've bolded the interesting part and here's the link to the wiki article (http://en.wikipedia.org/wiki/Memory_barrier#cite_note-1) and the associated reference (http://www.rdrop.com/users/paulmck/scalability/paper/whymb.2010.07.23a.pdf)

Here's the answer to your other question (from wikipedia): In C and C++, the volatile keyword was intended to allow C and C++ programs to directly access memory-mapped I/O. Memory-mapped I/O generally requires that the reads and writes specified in source code happen in the exact order specified with no omissions. Omissions or reorderings of reads and writes by the compiler would break the communication between the program and the device accessed by memory-mapped I/O. A C or C++ compiler may not reorder reads and writes to volatile memory locations, nor may it omit a read or write to a volatile memory location. The keyword volatile does not guarantee a memory barrier to enforce cache-consistency. Therefore the use of "volatile" alone is not sufficient to use a variable for inter-thread communication on all systems and processors[1]

Check this one out, it provides great explanations on the subject: http://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-1-of-2 http://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-2-of-2

like image 122
MasterPlanMan Avatar answered Oct 20 '22 04:10

MasterPlanMan


If access is protected by a mutex, you do not have any issue to worry about. The volatile keyword is useless here. A mutex is a full memory barrier and thus no object whose address could be externally visible can be cached across the mutex lock or unlock calls.

like image 37
R.. GitHub STOP HELPING ICE Avatar answered Oct 20 '22 04:10

R.. GitHub STOP HELPING ICE