C.6.2 Example 1

Table [*] shows three code fragments, executed concurrently by CPUs 0, 1, and 2. Each of ``a'', ``b'', and ``c'' are initially zero.


Table: Memory Barrier Example 1
CPU 0 CPU 1 CPU 2
a = 1;
smp_wmb(); while (b == 0);
b = 1; c = 1; z = c;
smp_rmb();
x = a;
assert(z == 0 || x == 1);


Suppose CPU 0 recently experienced many cache misses, so that its message queue is full, but that CPU 1 has been running exclusively within the cache, so that its message queue is empty. Then CPU 0's assignment to ``a'' and ``b'' will appear in Node 0's cache immediately (and thus be visible to CPU 1), but will be blocked behind CPU 0's prior traffic. In contrast, CPU 1's assignment to ``c'' will sail through CPU 1's previously empty queue. Therefore, CPU 2 might well see CPU 1's assignment to ``c'' before it sees CPU 0's assignment to ``a'', causing the assertion to fire, despite the memory barriers.

In theory, portable code cannot rely on this example code sequence, however, in practice it actually does work on all mainstream computer systems.

Quick Quiz C.10: Could this code be fixed by inserting a memory barrier between CPU 1's ``while'' and assignment to ``c''? Why or why not? End Quick Quiz

Paul E. McKenney 2011-12-16