2

I was trying to understand memory barrier and came across the below wikipedia link http://en.wikipedia.org/wiki/Memory_barrier This explain the concept well but had thoughts if this is really helpful in system where we have mutex() locking the memory section.

Taking the same code as mentioned in wikipedia, will the below approach solve the problem using mutex?

[Note: Function names are not specific to any programming language, just used for simplicity sake]

Processor #1

mutex_lock(a)
while (f == 0);
print x;
mutex_unlock(a)

Processor #2

mutex_lock(a)
x = 42;
f = 1;
mutex_unlock(a)
pkumarn
  • 1,383
  • 4
  • 22
  • 29
  • 3
    The example will deadlock if processor #1 acquires the lock first, because then processor #1 spins forever while processor #2 get stuck trying to acquire the lock. – Arch D. Robison Feb 27 '15 at 18:22

3 Answers3

13

A memory barrier guarantees that all visible effects of prior instructions become observable before those of any subsequent instructions. Things that might reorder the observed order of effects are:

  • Compilers (by reordering instructions)
  • Out of order pipelines
  • Cache systems with relaxed memory consistency (practically all on modern systems)

A mutex guarantees that only one thread holds the mutex at a time.

There is a relationship between the two concepts: a mutex is practically useless without at least partial memory barriers. Consider this example:

mutex_lock(a);
x = x+1;
mutex_unlock(a);

The lock operation must have at least an "acquire" barrier that prevents the load of x from appearing to happen before the lock is acquired. Likewise, the "unlock" operation must have at least a "release" barrier that prevents the store of x from appearing to happen after the lock is released. That is the lock-unlock pair form a cage from which operations cannot escape. (Though sometimes programmers are surprised when reordering causes operations to crawl into the cage!)

So locking a mutex and immediately unlocking it acts as a memory barrier, albeit a horribly inefficient one since it forces serial execution.

Arch D. Robison
  • 3,829
  • 2
  • 16
  • 26
  • Hi @Arch D. Robison +1 the concept of memory barrier refers **only** to the fact that the update of a global variable from a particular thread **may**not be visible to the other thread, i.e. one thread may be left with **obsolete (old) values, right**? THANKS IN ADVANCE –  Feb 10 '23 at 02:34
  • 1
    The general rule is that if there is a write on thread A and read on thread B for the same location, A has to execute a release operation as part of its write or as a subsequent memory barrier, and B has to execute an acquire operation as part of its read or as a preceding memory barrier, otherwise there is no guarantee that B will read the value written by A. – Arch D. Robison Feb 28 '23 at 03:26
  • Excellent @Arch D. Robison +1, thank you very much for this "summary", because of this general rule, I was confused about this memory barrier issue. –  Feb 28 '23 at 23:08
6

Mutex and other lock in kernel uses the barrier internally to ensure that code runs in the exact order as expected. When using optimization in compliers, You should never assume that instructions will be performed in the exact same order as written in the source code. Compiler might reorder the assembly language instructions in such a way to optimize how registers are used. Moreover, modern CPUs usually execute several instructions in parallel and might reorder memory accesses. These kinds of reordering can greatly speed up the program. But can result into unexpected output!

Hence MEMORY BARRIER primitive ensures that the assembly language instructions corresponding to C statements placed before the primitive are not mixed by the compiler with assembly language instructions corresponding to C statements placed after the primitive. In linux barrier() macro is:

asm volatile("":::"memory")

Here is the explanation:

  1. asm instruction tells the compiler to insert an assembly language fragment
  2. volatile keyword forbids the compiler to reshuffle the asm instruction with the other instructions of the program
  3. The memory keyword forces the compiler to assume that all memory locations in RAM have been changed by the assembly language instruction; therefore, the compiler cannot optimize the code by using the values of memory locations stored in CPU registers before the asm instruction
skaushal
  • 695
  • 3
  • 11
2

A memory bar usually is used to get out-of-order capable pipelines into a well-defined state with respect to their memory accesses, and thus are orthogonal to the concept of mutexes, which typically are a far much higher-level concept in multiprocessing (and have nothing to do with out-of-order execution of CPU instructions).

Marcus Müller
  • 34,677
  • 4
  • 53
  • 94