Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are volatile reads and writes atomic on Windows+VisualC?

There are a couple of questions on this site asking whether using a volatile variable for atomic / multithreaded access is possible: See here, here, or here for example.

Now, the C(++) standard conformant answer is obviously no.

However, on Windows & Visual C++ compiler, the situation seems not so clear.

I have recently answered and cited the official MSDN docs on volatile

Microsoft Specific

Objects declared as volatile are (...)

  • A write to a volatile object (volatile write) has Release semantics; a reference to a global or static object? that occurs before a write to a volatile object in the instruction sequence will occur before that volatile write in the compiled binary.
  • A read of a volatile object (volatile read) has Acquire semantics; a reference to a global or static object? that occurs after a read of volatile memory in the instruction sequence will occur after that volatile read in the compiled binary.

This allows volatile objects to be used for memory locks and releases in multithreaded applications.

[emphasis mine]

Now, reading this, it would appear to me that a volatile variable will be treated by the MS compiler as std::atomic would be in the upcoming C++11 standard.

However, in a comment to my answer, user Hans Passant wrote "That MSDN article is very unfortunate, it is dead wrong. You can't implement a lock with volatile, not even with Microsoft's version. (...)"


Please note: The example given in the MSDN seems pretty fishy, as you cannot generally implement a lock without atomic exchange. (As also pointed out by Alex.) This still leaves the question wrt. to the validity of the other infos given in this MSDN article, especially for use cases like here and here.)


Additionally, there are the docs for The Interlocked* functions, especially InterlockedExchange with takes a volatile(!?) variable and does an atomic read+write. (Note that one question we have on SO -- When should InterlockedExchange be used? -- does not authoritatively answer whether this function is needed for a read-only or write-only atomic access.)

What's more, the volatile docs quoted above somehow allude to "global or static object", where I would have thought that "real" acquire/release semantics should apply to all values.

Back to the question

On Windows, with Visual C++ (2005 - 2010), will declaring a (32bit? int?) variable as volatile allow for atomic reads and writes to this variable -- or not?

What is especially important to me is that this should hold (or not) on Windows/VC++ independently of the processor or platform the program runs on. (That is, does it matter whether it's a WinXP/32bit or a Windows 2008R2/64bit running on Itanum2?)

Please back up your answer with verifiable information, links, test-cases!

like image 437
Martin Ba Avatar asked Aug 10 '11 07:08

Martin Ba


1 Answers

Yes they are atomic on windows/vc++ (Assuming you meet alignment requirements etc or course)

However for a lock you would need an atomic test and set, or compare and exchange instuction or similar, not just an atomic update or read.

Otherwise there is no way to test the lock and claim it in one indivisable operation.

EDIT: As commented below, all aligned memory accesses on x86 of 32bit or below are atomic anyway. The key point is that volatile makes the memory accesses ordered. (Thanks for pointing this out in the comments)

like image 168
jcoder Avatar answered Oct 03 '22 02:10

jcoder