Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does the C++11 memory model allow hoisting relaxed atomic loads out of loops?

Tags:

c++

c++11

atomic

Consider the following code:

#include <atomic>

extern std::atomic<int> i;

void f(void)
{
  while (!i.load(std::memory_order_relaxed))
      ;
}

I'm looking for a citation from the C++11 standard that says that the compiler is not allowed to transform the loop into

  if (!i.load(std::memory_order_relaxed)) {
    while (1)
      ;
  }

I've seen some discussion here but nothing conclusive.

Edit: A previous version of this post called an extern function inside the loop.

Edit 2: For motivation: The book "Effective Java" says that the HotSpot VM performs the following transformation:

while (!done)
    i++;

to

if (!done)
    while (true)
        i++;

even though it's perfectly defined behavior for another thread to change the done variable concurrently.

like image 936
MuhKarma Avatar asked Oct 26 '16 21:10

MuhKarma


People also ask

What is the purpose of memory model in C++?

The purpose of a memory model is to enable thread communication. When one thread writes values to memory and another thread reads from memory, the memory model dictates what values the reading thread might see. LockingLocking is typically the easiest way to share data among threads.

How does compiler optimization affect the Order of memory operations?

Also, certain compiler optimizations can result in reordering of memory operations. Notably, if several reads access the same memory location, the compiler might choose to perform the read only once and keep the value in a register for subsequent reads.

What types can be written atomically in C?

The C# ECMA specification guarantees that the following types will be written atomically: reference types, bool, char, byte, sbyte, short, ushort, uint, int and float. Values of other types—including user-defined value types—could be written into memory in multiple atomic writes.

Does the compiler reorder memory operations when converting C to Il?

In the .NET Framework 4.5, the csc.exe compiler that compiles C# to IL doesn’t do many optimizations, so it won’t reorder memory operations. However, the just-in-time (JIT) compiler that converts IL to machine code will, in fact, perform some optimizations that reorder memory operations, as I’ll discuss.


1 Answers

Forget about relaxed, there's no guarantee that an atomic store ever become visible to an atomic load in a different thread. The best you get is the normative encouragement in [atomics.order]/12 (and analogous wording in [intro.progress]/18):

Implementations should make atomic stores visible to atomic loads within a reasonable amount of time.

...which is not a requirement.

(C11 has identical wording in §7.11.3/16)

Since hoisting the load leads to behavior indistinguishable from a non-hoisted load where the store never becomes visible, and since the latter is conforming, an implementation is allowed by the as-if rule to hoist the load regardless of the memory order used.

like image 141
T.C. Avatar answered Oct 13 '22 23:10

T.C.