Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Memory Barriers for Atomics

I'm a newbie when it comes to this. Could anyone provide a simplified explanation of the differences between the following memory barriers?

  • The windows MemoryBarrier();
  • The fence _mm_mfence();
  • The inline assembly asm volatile ("" : : : "memory");
  • The intrinsic _ReadWriteBarrier();

If there isn't a simple explanation some links to good articles or books would probably help me get it straight. Until now I was fine with just using objects written by others wrapping these calls but I'd like to have a better understanding than my current thinking which is basically along the lines of there is more than one way to implement memory barriers under the covers.

like image 981
AJG85 Avatar asked Jan 12 '12 20:01

AJG85


People also ask

What is memory barrier in C?

In computing, a memory barrier, also known as a membar, memory fence or fence instruction, is a type of barrier instruction that causes a central processing unit (CPU) or compiler to enforce an ordering constraint on memory operations issued before and after the barrier instruction.

How do memory barriers work?

The memory barrier instructions halt execution of the application code until a memory write of an instruction has finished executing. They are used to ensure that a critical section of code has been completed before continuing execution of the application code.

What does __ Sync_synchronize do?

__sync_synchronize This function synchronizes data in all threads. A full memory barrier is created when this function is invoked.


1 Answers

Both MemoryBarrier (MSVC) and _mm_mfence (supported by several compilers) provide a hardware memory fence, which prevents the processor from moving reads and writes across the fence.

The main difference is that MemoryBarrier has platform specific implementations for x86, x64 and IA64, where as _mm_mfence specifically uses the mfence SSE2 instruction, so it's not always available.

On x86 and x64 MemoryBarrier is implemented with a xchg and lock or respectively, and I have seen some claims that this is faster than mfence. However my own benchmarks show the opposite, so apparently it's very much dependent on processor model.

Another difference is that mfence can also be used for ordering non-temporal stores/loads (movntq etc).

GCC also has __sync_synchronize which generates a hardware fence.

asm volatile ("" : : : "memory") in GCC and _ReadWriteBarrier in MSVC only provide a compiler level memory fence, preventing the compiler from reordering memory accesses. That means the processor is still free to do reordering.

Compiler fences are generally used in combination with operations that have some kind of implicit hardware fence. E.g. on x86/x64 all stores have a release fence and loads have an acquire fence, so you just need a compiler fence when implementing load-acquire and store-release.

like image 101
Timo Avatar answered Sep 24 '22 10:09

Timo