C.6.4 Example 3

Table [*] shows three code fragments, executed concurrently by CPUs 0, 1, and 2. All variables are initially zero.


Table: Memory Barrier Example 3
CPU 0 CPU 1 CPU 2
1 a = 1;
2 smb_wmb();
3 b = 1; while (b == 0); while (b == 0);
4 smp_mb(); smp_mb();
5 c = 1; d = 1;
6 while (c == 0);
7 while (d == 0);
8 smp_mb();
9 e = 1; assert(e == 0 || a == 1);


Note that neither CPU 1 nor CPU 2 can proceed to line 5 until they see CPU 0's assignment to ``b'' on line 3. Once CPU 1 and 2 have executed their memory barriers on line 4, they are both guaranteed to see all assignments by CPU 0 preceding its memory barrier on line 2. Similarly, CPU 0's memory barrier on line 8 pairs with those of CPUs 1 and 2 on line 4, so that CPU 0 will not execute the assignment to ``e'' on line 9 until after its assignment to ``a'' is visible to both of the other CPUs. Therefore, CPU 2's assertion on line 9 is guaranteed not to fire.

Quick Quiz C.11: Suppose that lines 3-5 for CPUs 1 and 2 in Table [*] are in an interrupt handler, and that the CPU 2's line 9 is run at process level. What changes, if any, are required to enable the code to work correctly, in other words, to prevent the assertion from firing? End Quick Quiz

Quick Quiz C.12: If CPU 2 executed an assert(e==0||c==1) in the example in Table [*], would this assert ever trigger? End Quick Quiz

The Linux kernel's synchronize_rcu() primitive uses an algorithm similar to that shown in this example.

Paul E. McKenney 2011-12-16