dicroce
dicroce

Reputation: 46800

Detect at runtime if a load is atomic?

My application requires a couple of atomic loads and stores. Unfortunately, these operations must occur at a particular address in a memory mapped file and so I cannot use c++11's std::atomic (since std::atomic works by controlling the size and alignment/placement of the variable. Since I control the memory mapped file format and we only run on a single CPU architecture I simply looked up the alignment and size constraints of my target and arranged things to allow for the atomicity (including a full fence at just the right spot).

Is there a way to test (at runtime) if a read or a write of a particular size to a particular address would be atomic? My primary platform is x86-64 but I'd also be interested in solutions for ARM.

Upvotes: 1

Views: 199

Answers (1)

Mats Petersson
Mats Petersson

Reputation: 129474

Short answer: Probably not. You could write some code that updates and checks validity of your values, and run that for 6 months. However, it will almost certainly not GUARANTEE that the code is correct - just that you haven't hit the right spot to make it go wrong.

Long answer: Loads and stores of processor words are almost certainly atomic in and of themselves, however the std::atomic functionality provides a stronger guarantee than that. It guarantees that no processor will use a value that is "stale" (cache-coherency and exclusive updates). You can't make the same guarantee without std::atomic (unless the platform itself guarantees this, which would probably require it to be a single core processor at the very least).

In a generic case, loads and stores as performed by the processor has a "weak" cache coherency and atomic update policy. Say we have this code:

 int a = 42; 
 bool flag = false;

 ... 

 a++;
 flag = true;

and some other code that does:

 while(!flag)
 a--;

[I'm currently ignoring the fact that flag also needs atomic update policy and probably needs to be volatile - that is not the point in this case]

There is no guarantee that the compiler doesn't form tmp = a; tmp = tmp+1; a = tmp; (and corresponding for the a--) [possibly with extra instructions thrown in between for good measure, because the compiler expects that to be faster/better in some other way].

There is also no guarantee that the value won't have been updated to 43, but the other code has read the old 42 value after it exits the loop because flag is true (because the processor is not doing everything in exactly the order you expect, and the cache-content is updated "out of order").

x86-processors are definitely among the ones that have not got guarantees that the updated value will be immediately available as described above. Cache coherency and atomicity just guarantees that you won't read some "half-baked" value - it's either the "old" or the "new" value when updating a value - but it may be the "old" value for quite some time after the "new" value has been written, which is typically "not a good thing".

Upvotes: 1

Related Questions