[PATCH v2 5/5] Doc/memory-barriers: add Korean translation
From: SeongJae Park
Date:  Thu Mar 10 2016 - 10:08:05 EST
This commit adds Korean version of memory-barriers.txt document.  The
header is refered to HOWTO Korean version.
Signed-off-by: SeongJae Park <sj38.park@xxxxxxxxx>
Acked-by: David Howells <dhowells@xxxxxxxxxx>
---
 Documentation/ko_KR/memory-barriers.txt | 3048 +++++++++++++++++++++++++++++++
 1 file changed, 3048 insertions(+)
 create mode 100644 Documentation/ko_KR/memory-barriers.txt
diff --git a/Documentation/ko_KR/memory-barriers.txt b/Documentation/ko_KR/memory-barriers.txt
new file mode 100644
index 0000000..38bfa55
--- /dev/null
+++ b/Documentation/ko_KR/memory-barriers.txt
@@ -0,0 +1,3048 @@
+NOTE:
+This is a version of Documentation/memory-barriers.txt translated into Korean.
+This document is maintained by SeongJae Park <sj38.park@xxxxxxxxx>.
+If you find any difference between this document and the original file or
+a problem with the translation, please contact the maintainer of this file.
+
+Please also note that the purpose of this file is to be easier to
+read for non English (read: Korean) speakers and is not intended as
+a fork.  So if you have any comments or updates for this file please
+try to update the original English file first.
+
+===================================
+ì ëìë
+Documentation/memory-barriers.txt
+ì íê ëììëë.
+
+ììï ëìì <sj38.park@xxxxxxxxx>
+===================================
+
+
+			 =========================
+			 ëëì ìë ëëë ëëì
+			 =========================
+
+ìì: David Howells <dhowells@xxxxxxxxxx>
+      Paul E. McKenney <paulmck@xxxxxxxxxxxxxxxxxx>
+
+ëì:
+
+ (*) ìì ëëë ììì ëë.
+
+     - ëëìì ìíëìì.
+     - ëììíë.
+
+ (*) ëëë ëëìëìë ëììê?
+
+     - ëëë ëëìì ìëë.
+     - ëëë ëëìëì ëí êìíì ìë êë.
+     - ëìí ììì ëëì.
+     - ìíë ììì.
+     - SMP ëëì ìëìê.
+     - ëëë ëëì ìíìì ì.
+     - ìê ëëë ëëì vs ëë ìííëìì.
+     - íëì
+
+ (*) ëìì ìë ëëìë.
+
+     - ìíìë ëëì.
+     - CPU ëëë ëëì.
+     - MMIO ìê ëëì.
+
+ (*) ìëì ìë ëëë ëëì.
+
+     - Acquiring íì.
+     - ìíëí ëíìí íì.
+     - ìëê ììíì íì.
+     - êìì íìë.
+
+ (*) CPU ê ACQUIRING ëëìì íê.
+
+     - Acquire vs ëëë ììì.
+     - Acquire vs I/O ììì.
+
+ (*) ëëë ëëìê íìí ê
+
+     - íëììê ìí ìì.
+     - ìíë ìíëìì.
+     - ëëìì ììì.
+     - ìíëí.
+
+ (*) ìë I/O ëëìì íê.
+
+ (*) êìëë ììíì ìí ìì ëë.
+
+ (*) CPU ììì ìí.
+
+     - ìì ìêì.
+     - ìì ìêì vs DMA.
+     - ìì ìêì vs MMIO.
+
+ (*) CPU ëì ììëë ìë.
+
+     - êëê Alpha ê ìë.
+     - êì ëì êìí.
+
+ (*) ìì ì.
+
+     - ìíì ëí.
+
+ (*) ìê ëí.
+
+
+=======================
+ìì ëëë ììì ëë
+=======================
+
+ëìê êì ììíë ììí ëëì ìêí ëìë:
+
+		            :                :
+		            :                :
+		            :                :
+		+-------+   :   +--------+   :   +-------+
+		|       |   :   |        |   :   |       |
+		|       |   :   |        |   :   |       |
+		| CPU 1 |<----->| Memory |<----->| CPU 2 |
+		|       |   :   |        |   :   |       |
+		|       |   :   |        |   :   |       |
+		+-------+   :   +--------+   :   +-------+
+		    ^       :       ^        :       ^
+		    |       :       |        :       |
+		    |       :       |        :       |
+		    |       :       v        :       |
+		    |       :   +--------+   :       |
+		    |       :   |        |   :       |
+		    |       :   |        |   :       |
+		    +---------->| Device |<----------+
+		            :   |        |   :
+		            :   |        |   :
+		            :   +--------+   :
+		            :                :
+
+ê CPU ë ëëë ììì ìíëììëì ììíëë íëêëì ìííëë.
+ììíë CPU ìì, ëëë ìíëìì ììë ëì ìíëì ìê, CPU ë
+íëêëì ìêêêë ìêì ìê êëëëê ëì ìë ìëë ëëë
+ìíëììëì ììì ìíë ìë ììëëë ìëìí ìíí êìëë.
+ììíê, ìíìë ëí íëêëì ììì ëìì ëêëëì ìë íë ëììë
+ììì ìíëëë ìë ììëë ëëìëì ìëì í êìëë.
+
+ëëì ìì ëìêëìì, í CPUê ìííë ëëë ìíëììì íêë
+ìíëììì CPU ì ììíì ëë ëëë ììì ìííìì(ìì) ë ìëê ë
+ììíì ëëì ëëëì ìíëëë.
+
+
+ìë ëì, ëìì ìëì ìëíëì ìêíëìë:
+
+	CPU 1		CPU 2
+	===============	===============
+	{ A == 1; B == 2 }
+	A = 3;		x = B;
+	B = 4;		y = A;
+
+ëëë ììíì ëììê ë ìêì ìììëì ëìì ì 24ê ìë ëë ìíìë
+ìêìë ì ììëë:
+
+	STORE A=3,	STORE B=4,	y=LOAD A->3,	x=LOAD B->4
+	STORE A=3,	STORE B=4,	x=LOAD B->4,	y=LOAD A->3
+	STORE A=3,	y=LOAD A->3,	STORE B=4,	x=LOAD B->4
+	STORE A=3,	y=LOAD A->3,	x=LOAD B->2,	STORE B=4
+	STORE A=3,	x=LOAD B->2,	STORE B=4,	y=LOAD A->3
+	STORE A=3,	x=LOAD B->2,	y=LOAD A->3,	STORE B=4
+	STORE B=4,	STORE A=3,	y=LOAD A->3,	x=LOAD B->4
+	STORE B=4, ...
+	...
+
+ëëì ëìì ëêì ìë ëë êêêì ìíì ëì ì ììëë:
+
+	x == 2, y == 1
+	x == 2, y == 3
+	x == 4, y == 1
+	x == 4, y == 3
+
+
+ëìì, í CPU ì ìí ëëë ììíì ííì ìì ëìëì ëë CPU ì ìê
+ëìëì ììì ííì ììì ëë ììë ìíì ì ììëë.
+
+
+ìë, ì ìëì ìëíëì ìêí ëìë:
+
+	CPU 1		CPU 2
+	===============	===============
+	{ A == 1, B == 2, C == 3, P == &A, Q == &C }
+	B = 4;		Q = P;
+	P = &B		D = *Q;
+
+ìêì ëëí ëìí ìììì ììíëë. D ë ìíìë êì CPU 2 ìì P
+ëëí ìíì ììêì ììììëë. ìëíëì ìëëìì ë, ìëì êêëì
+êëíëë:
+
+	(Q == &A) and (D == 1)
+	(Q == &B) and (D == 2)
+	(Q == &B) and (D == 4)
+
+CPU 2 ë *Q ì ëëë ììíê ìì P ë Q ì ëê ëëì D ì C ë ììëë
+ìì ììì ìì ëìì.
+
+
+ëëìì ìíëìì
+-------------------
+
+ìë ëëììëì êëì ìì ìííììë ëëë ììì ìíìë ìêíëëë,
+íë ìíë ëììíì ìêíë ììë ëì ììíëë.  ìë ëì, ìëëì
+íí ëììí (A) ì ëìí íí ëììí (D) ë íí ìêëë ëë ëììí
+ìíì êë ìëë ìëë ìêí ëìë.  ëëì 5ë ëììíë ììëë,
+ëìì ìëê ììë ì ìì êëë:
+
+	*A = 5;
+	x = *D;
+
+íìë ìê ëìì ë ìí ì íëë ëìì ì ìì êëë:
+
+	STORE *A = 5, x = LOAD *D
+	x = LOAD *D, STORE *A = 5
+
+ëëì ìíì ëìíë ììì _íì_ ììë ììíëë, ìëë ëìì ììí
+êìëë.
+
+
+ëììíë
+----------
+
+CPU ìê êëí ì ìë ììíì ëììíëì ìë ììëë:
+
+ (*) ìë CPU ë, ìììì ììíë ëëë ìììëì íë CPU ìììê
+     ìììë íë ìì êëë ììëëë. ì, ëìì ëíìë:
+
+	Q = READ_ONCE(P); smp_read_barrier_depends(); D = READ_ONCE(*Q);
+
+     CPU ë ëìê êì ëëë ìíëììëì ììíëë:
+
+	Q = LOAD P, D = LOAD *Q
+
+     êëê ê ììë íì ìììëë.  ëëëì ììíìì,
+     smp_read_barrier_depends() ë ìëìë ìíëëë, DEC Alpha ììë
+     íìíëë.  ëíì êì ëìì smp_read_barrier_depends() ë ìì
+     ììíë ëì rcu_dereference() êì êëì ììíì í êëë.
+
+ (*) íì CPU ëìì êìì ííìë ëëì ìíì ëì ê CPU ìììë ììê
+     ëìì êìë ëíëëë.  ì, ëìì ëíì:
+
+	a = READ_ONCE(*X); WRITE_ONCE(*X, b);
+
+     CPU ë ëìì ëëë ìíëìì ëìëì ëëëì ììí êìëë:
+
+	a = LOAD *X, STORE *X = b
+
+     êëê ëìì ëíìë:
+
+	WRITE_ONCE(*X, c); d = READ_ONCE(*X);
+
+     CPU ë ìëì ëìì ëëëì ëëë:
+
+	STORE *X = c, d = LOAD *X
+
+     (ëëì ìíìë êì ëëë ììì íêìë í ëì êììëë).
+
+êëê _ëëì_ ëë _ìëë_ êìíêë íì ëìì íë êëì ììëë:
+
+ (*) ìíìëê READ_ONCE() ë WRITE_ONCE() ë ëíëì ìì ëëë ììì ëí
+     ëìì ìíë ëë í êìëë êìì _ìëë_ íì ìëëë.  êêëì
+     ìëë, ìíìëë ìíìë ëëì ìììì ëëê ë, ëë "ìììì"
+     ëêëì ëë êíì êìê ëëë.
+
+ (*) êëìì ëëì ìíìëì ììì ììëë ììë êìëë êìì _ìëë_
+     íì ëìì íëë.  ì ëì ì:
+
+	X = *A; Y = *B; *D = Z;
+
+     ë ëìì ììë ì ìë êìë ëëìì ì ìëë ìëìëë:
+
+	X = LOAD *A,  Y = LOAD *B,  STORE *D = Z
+	X = LOAD *A,  STORE *D = Z, Y = LOAD *B
+	Y = LOAD *B,  X = LOAD *A,  STORE *D = Z
+	Y = LOAD *B,  STORE *D = Z, X = LOAD *A
+	STORE *D = Z, X = LOAD *A,  Y = LOAD *B
+	STORE *D = Z, Y = LOAD *B,  X = LOAD *A
+
+ (*) êìë ëëë ìììëì ëíëêë ëëì ì ììì _ëëì_ êìíì
+     íëë.  ëìì ìëë:
+
+	X = *A; Y = *(A + 4);
+
+     ëìì ììíëì íë ì ëë ë ì ììëë:
+
+	X = LOAD *A; Y = LOAD *(A + 4);
+	Y = LOAD *(A + 4); X = LOAD *A;
+	{X, Y} = LOAD {*A, *(A + 4) };
+
+     êëê:
+
+	*A = X; *(A + 4) = Y;
+
+     ë ëì ì ëë êëíëë:
+
+	STORE *A = X; STORE *(A + 4) = Y;
+	STORE *(A + 4) = Y; STORE *A = X;
+	STORE {*A, *(A + 4) } = {X, Y};
+
+êëê ìí-ëììíëì ììëë:
+
+ (*) ì ëììíëì bitfields ìë ììëì ìëë, ìíìëëì ìêëì
+     ììì ìë read-modify-write ëìë ëêë ìëë ììíê ëëìëë.
+     ëë ìêëìì ëêíì bitfields ë ììíë íì ëììì.
+
+ (*) bitfields ê ìë ëìë ëíëë êìë íëëë, ììì bitfield ì ëë
+     íëëì íëì ëìë ëíëìì íëë.  ëì í bitfield ì ë íëê
+     ìë ëë ëìë ëíëëë, ìíìëì ììì ìë read-modify-write
+     ëìëì í íëìì ìëìíê êìì íëìë ìíì ëì ì ììëë.
+
+ (*) ì ëììíëì ììíê ìëëê íêê ìí ììë ëìëì ëíìë
+     ììëëë.  "ììíê íêê ìí" ìëíì íìëìë "char", "short",
+     "int" êëê "long" ê êì íêì ëìëì ìëíëë.  "ììíê ìëë"
+     ì ìììì ìëì ìëíëë, ëëì "char" ì ëíìë ìë ììì ìê,
+     "short" ì ëíìë 2ëìí ìëì, "int" ìë 4ëìí ìëì, êëê
+     "long" ì ëíìë 32-bit ììíìì 64-bit ììíììì ëë 4ëìí ëë
+     8ëìí ìëì ìëíëë.  ì ëììíëì C11 íììì ìêëììëë,
+     C11 ììì ìëë ìíìë(ìë ëì, gcc 4.6) ë ììí ëì ììíìê
+     ëëëë.  íìì ì ëììíëì "memory location" ì ììíë 3.14
+     ììì ëìê êì ìëëì ììëë:
+     (ìì: ììëìëë ëìíì ììëë)
+
+     	memory location
+		either an object of scalar type, or a maximal sequence
+		of adjacent bit-fields all having nonzero width
+
+		NOTE 1: Two threads of execution can update and access
+		separate memory locations without interfering with
+		each other.
+
+		NOTE 2: A bit-field and an adjacent non-bit-field member
+		are in separate memory locations. The same applies
+		to two bit-fields, if one is declared inside a nested
+		structure declaration and the other is not, or if the two
+		are separated by a zero-length bit-field declaration,
+		or if they are separated by a non-bit-field member
+		declaration. It is not safe to concurrently update two
+		bit-fields in the same structure if all members declared
+		between them are also bit-fields, no matter what the
+		sizes of those intervening bit-fields happen to be.
+
+
+=============================
+ëëë ëëìëìë ëììê?
+=============================
+
+ììì ëëì, êëì ëëë ìíëììëì ììëë ëììì ììë ìíë ì
+ììëëë, ìêì CPU ì CPU ê ìíììê I/O ì ëìê ë ì ììëë.
+ëëì ìíìëì CPU ê ëêë ììì êìí ì ìë ìë ëëì íìíëë.
+
+ëëë ëëìëì êë êìëëìëë.  ëëë ëëìëì ëëìë ììì ë
+ììì ëëë ìíëììë êì ëëì ììê ììíë íêë ìëë.
+
+ììíì CPU ëê ëë ëëììëì ìëì ìëê ìí ìëì, ìì êëê
+ëëë ìíëììëì ìí; íêì ëë; íêì ëëì ìì êëê ëìí ìì
+ëì ëìí íëì ììí ì ìê ëëì ìë êìëì ììíëë.  ëëë
+ëëìëì ìë íëëì ëíë íêë ììíê ìí ììëììì ìëê ìë
+CPU ì/ëë ëëììë êì ìíììì ììììë ëë ì ìê íìëë.
+
+
+ëëë ëëìì ìëë
+----------------------
+
+ëëë ëëìëì ëêì êë ìëë ëëëëë:
+
+ (1) ìê (ëë ìíì) ëëë ëëìë.
+
+     ìê ëëë ëëìë ììíì ëë ìíëíëì íë ëëì ìì ëìë
+     ëë STORE ìíëììëì íë ëëì ëì ëìë ëë STORE
+     ìíëììëëë ëì ìíë êê êì ëì êì ëìíëë.
+
+     ìê ëëìë ìíì ìíëììëëì ëí ëëì ìì ììêìëë; ëë
+     ìíëììëì ëíìë ìë ìíë ëìì ììëë.
+
+     CPU ë ìêì íëì ëë ëëë ììíì ìëì ìíì ìíëììëì
+     íëì ììëìëë.  ëë ìê ëëì ììì ìíì ìíëììëì ê
+     ìê ëëì ëì ëë ìíì ìíëììëëë _ìì_ ê ììëë ííì
+     êìëë.
+
+     [!] ìê ëëìëì ìê ëë ëìí ììì ëëìì íê ìì ëì
+     ììëìììë íì ììëìì; "SMP ëëì ìëìê" ìëììì
+     ìêíìì.
+
+
+ (2) ëìí ììì ëëì.
+
+     ëìí ììì ëëìë ìê ëëìì ëë ìí ííìëë.  ëêì ëë
+     ìíëììì ìê ëëì êì ìëì êì êêì ììíê ìì ë(ì:
+     ìëì ëëë ëëì ëëê ììí ììë ìë êì), ëëì ëëê ììì
+     ëìíë ìëì ëëì ìí ê ììê ìììê ìì ìëìí ëì ììì
+     ëëí íê ìí ëìí ììì ëëìê íìí ì ììëë.
+
+     ëìí ììì ëëìë ìí ìììì ëë ìíëììë ììì ëëì ìì
+     ììêìëë; ìíì ìíëììëìë ëëìì ëëë, ëë ìëëë
+     ëëëì ëíìë ìë ìíë ëìì ììëë.
+
+     (1) ìì ìêíë, ììíì ëë CPU ëì íë CPU ê ìë ëìì êì
+     ìíë ììí ì ìë ëëë ììíì ìëì ìíì ìíëììëì
+     ììëê ìë êìë ë ì ììëë.
+     íì ëìì êìì ëê ìë CPU ê ììíë ëìí ììì ëëìë ê
+     ìì ìë ëë ìíëììë ê ëëê ëë CPUê ììí ìíì
+     ìíëììëê êìë ììì ííëë, ëëìê ìëëë ììììë ê
+     ìì ëëì êìë ëë ìíì ìíëììëì ìëëì ììì ëìí
+     ëìí ììì ëëì ìíì ëë ìíëììëì ê ìíì ìíëììì
+     êêë ë ì ìê ëìíëë.
+
+     ì ìì ììê ììì ëí ëììêëì ìíì "ëëë ëëì ëìì ì"
+     ìëììì ìêíìê ëëëë.
+
+     [!] ìëì ëëë ëëì _ëìí_ ìììì êììì ìíë ìììì êìì
+     íëê ìëì ììëììì.  ëì ëëì ëëë ìí ììê ìëì ëëì
+     ìììììë ê ìììì ìêììì ê ìì ììë êììëê ìëëë,
+     êêì _ìíë_ ììììê ììí ëë ëëìë êëë êí ëìì
+     íìíëë. ë ììí ëìì ìíìë "ìíë ììì" ìëììì
+     ìêíìê ëëëë.
+
+     [!] ëìí ììì ëëìë ëí ìê ëëìëê íê ìì ëì ììëìì
+     íëë; "SMP ëëì ìëìê" ìëììì ìêíìì.
+
+
+ (3) ìê (ëë ëë) ëëë ëëìë.
+
+     ìê ëëìë ëìí ëíëìì êëì ìêë ëëì ììì ëìë ëë
+     LOAD ìíëììëì ëëì ìíì ëìëë ëë LOAD ìíëììëëë ëì
+     ííì êìë ììíì ëë ìíëíëì ëìì êì ëìíëë.
+
+     ìê ëëìë ëë ìíëììì ííìë ëëì ìì ììêìëë; ìíì
+     ìíëììì ëíìë ìë ìíë ëìì ììëë.
+
+     ìê ëëë ëëìëì ëìí ììì ëëìë ëìíëë ëìí ììì
+     ëëìëì ëìí ì ììëë.
+
+     [!] ìê ëëìëì ëí ìê ëëìëê ìì ëì ììëìì íëë; "SMP
+     ëëì ìëìê" ìëììì ìêíìì.
+
+
+ (4) ëì ëëë ëëìë.
+
+     ëì ëëë ëëìë ììíì ëëì ìíëíëì ëëìëë ìì ëìë
+     ëë LOAD ì STORE ìíëììëì ëëì ìíì ëìë ëë LOAD ì STORE
+     ìíëììëëë ëì ìíë êìë ììíì ëëì ìíëíëì ëìê
+     ëì ëìíëë.
+
+     ëì ëëë ëëìë ëëì ìíì ëëì ëí ëëì ìì ììêìëë.
+
+     ëì ëëë ëëìë ìê ëëë ëëì, ìê ëëë ëëì ëëë
+     ëìíëë, ê ëëì ëëë ëìí ì ììëë.
+
+
+êëê ìêì ëììì ëíë:
+
+ (5) ACQUIRE ìíëììë.
+
+     ì ìíëììëì ëëíì íêì ëëììë ëìíëë.  ACQUIRE
+     ìíëìì ìíì ëë ëëë ìíëììëì ACQUIRE ìíëìì ìíì
+     ììë êìë ììíì ëëì ìíëíëì ëìê ë êì ëìëëë.
+     LOCK ìíëììê smp_load_acquire() ìíëììë ACQUIRE ìíëììì
+     ìììëë.
+
+     ACQUIRE ìíëìì ììì ììë ëëë ìíëììëì ACQUIRE ìíëìì
+     ìë ìíì ììë êìë ëì ìë ììëë.
+
+     ACQUIRE ìíëììì êì íì RELEASE ìíëììê ìì ìì ììëìì
+     íëë.
+
+
+ (6) RELEASE ìíëììë.
+
+     ìêëë ëëí íêì ëëììë ëìíëë.  RELEASE ìíëìì ììì
+     ëë ëëë ìíëììëì RELEASE ìíëìì ììì ìëë êìë
+     ììíì ëë ìíëíëì ëìì êì ëìëëë.  UNLOCK ìíëììëê
+     smp_store_release() ìíëììëë RELEASE ìíëììì ìììëë.
+
+     RELEASE ìíëìì ìíì ììë ëëë ìíëììëì RELEASE
+     ìíëììì ìëëê ìì ííì êìë ëì ì ììëë.
+
+     ACQUIRE ì RELEASE ìíëììì ììì ìëììë ëë ëëë ëëìì
+     íììì ììëë (íìë "MMIO ìê ëëì" ìëìììì ìëëë ììë
+     ììëìì).  ëí, RELEASE+ACQUIRE ìíì ìì ëëë ëëììë ëìí
+     êì ëìíì -ììëë-.  íìë, ìë ëìì ACQUIRE ìíëììì í
+     ìíìë êì ëìì ëí RELEASE ììì ìíë ëëë ìììë ëìì
+     êì ëìëëë.  ëë ëíìë, ììì ëìì íëíì ììììë, íë
+     ëìì ëí ëë ìì íëíì ììììì ìììëì ìëëìì êì
+     ëìíëë.
+
+     ì, ACQUIRE ë ììíì "ìë" ëììë, êëê RELEASE ë ììíì "êê"
+     ìë ëìíëë ìëìëë.
+
+
+ëëë ëëìëì ë CPU ê, ëë CPU ì ëëìì êì ìíììì êëìì ìì
+ëìë íìíëë.  ëì ìë ìëì êë ìíììì ìì êìì ëìëëë,
+íë ìëììë ëëë ëëìë ììí íìê ììëë.
+
+
+ìêëì _ììíì_ ëììíëìì ììëìì. ëë ìííìììë ë êëí
+ëììíëì ìêí ìë ììëë, íìë êë ëììíëì ìííìì ëêí
+ìëììë ìëíì _ìììë_ ììëë.
+
+
+ëëë ëëìëì ëí êìíì ìë êë
+-----------------------------------------
+
+ëëì ìë ëëë ëëìëì ëìíì ìë êëì ìë ììëë:
+
+ (*) ëëë ëëì ììì ëìë ìë ëëë ìììë ëëë ëëì ëëì ìí
+     ìë ììêì _ìë_ ë êìë ëìì ììëë; ëëìê íë ìì CPU ì
+     ììì íì ìë íëëë íìì ìììëì ëì ì ìë ìì êë êìë
+     ìíí ì ììëë.
+
+ (*) í CPU ìì ëëë ëëìë ììíë êì ììíì ëë CPU ë íëììì
+     ìë ìììì ìíì ëìëë ëìì ììíì ììëë.  êììì ìíì
+     ëëì CPU ê ëëëë ìëì CPU ì ìììëì ììì êíìëë, íìë
+     ëìì ëìì:
+
+ (*) í CPU ê ëëì CPU ì ëëë ìììëì êêë ììë íêë ìì
+     ììëë ëëë ëìì ììëë, _ìë_ ëëì CPU ê ëëë ëëìë
+     ììíë íë, ìëì CPU _ëí_ êì ëë ëëë ëëìë ììíì
+     ìëëë ëìì ("SMP ëëì ìëìê" ìëììì ìêíìì).
+
+ (*) CPU ëêì íëìì[*] ì ìëê ëëë ìììëì ììë ëêì ìëëë
+     ëìì ììëë.  CPU ìì ìêì ëìëìì ëëë ëëìì êìì ìíì
+     CPUë ììì ìííê íìë, ììëë ìííìë ìì ìë ììëë.
+
+	[*] ëì ëìíë DMA ì ìêìì ëíìë ëìì ìêíìê ëëëë:
+
+	    Documentation/PCI/pci.txt
+	    Documentation/DMA-API-HOWTO.txt
+	    Documentation/DMA-API.txt
+
+
+ëìí ììì ëëì
+--------------------
+
+ëìí ììì ëëìì ììì íìí ììì ìê ëëíê íì ê íìê
+ëëíìë ììëë.  ìëì ìí ëìì ìëí ìíìë ëìë:
+
+	CPU 1		      CPU 2
+	===============	      ===============
+	{ A == 1, B == 2, C == 3, P == &A, Q == &C }
+	B = 4;
+	<ìê ëëì>
+	WRITE_ONCE(P, &B)
+			      Q = READ_ONCE(P);
+			      D = *Q;
+
+ìêì ëëí ëìí ìììì ììíê, ì ìíìê ëëì ë, Q ë &A ëë &B
+ì êìê, ëëì:
+
+	(Q == &A) ë (D == 1) ë,
+	(Q == &B) ë (D == 4) ë ìëíëë.
+
+íìë!  CPU 2 ì P ììì ììì B ìì ììì ëìì ìë ìê, ëëì ëìì
+ìíì êëíëë:
+
+	(Q == &B) and (D == 2) ????
+
+ìê ìêììë ìê êê ììì ìíí êìë ëì ìë ìêìë, êëì
+ììëë, êëê ì íìì (DEC Alpha ì êì) ìë ìì CPU ìì ëêë ì
+ììëë.
+
+ìê ìëë íêíê ìí, ëìí ììì ëëìë êëë ëì êì ììë
+ììì ëì ëìíë ììì ë ììì ìêëììë íëë:
+
+	CPU 1		      CPU 2
+	===============	      ===============
+	{ A == 1, B == 2, C == 3, P == &A, Q == &C }
+	B = 4;
+	<ìê ëëì>
+	WRITE_ONCE(P, &B);
+			      Q = READ_ONCE(P);
+			      <ëìí ììì ëëì>
+			      D = *Q;
+
+ìêì ìì êìë êì ëêì ì íëëì ëìíê, ìëì êìë ëìí ì
+ìëë íëë.
+
+ììì ìêì ëíìë ëìí ììì ëëìê ëëììì íëë:
+
+	CPU 1		      CPU 2
+	===============	      ===============
+	{ A == 1, B == 2, C = 3, P == &A, Q == &C }
+	B = 4;
+	<ìê ëëì>
+	WRITE_ONCE(P, &B);
+			      Q = READ_ONCE(P);
+			      <ëìí ììì ëëì>
+			      *Q = 5;
+
+ì ëìí ììì ëëìë Q ëì ìêê *Q ëì ìíìì ììë ëìê
+íìëë.  ìë ëìê êì êêë ëìëë:
+
+	(Q == B) && (B == 4)
+
+ìë ííì íì ììì ìì ëìê ëëëë.  ëìëë, ììì ìì ììêì
+ììì ëìí êìëì ìêë -ëì-íë êìëë, êë ìêì ìêëë êëì
+ìì ëìëê íêì.  ì ííì íì ìì ìë ìêì êëíê êë êëì
+ìëìë êì ëëë ììë ì ììëë.
+
+
+[!] ëëí ëìêìì ì ìíì ëëë ììë êì êêë, ìë ëì í ìì
+ëíê ììë ìì ëìì ìëíê ëë ëíë íìë ìì ëìì ìëíë êì
+ëìì êì ì ëìíëë.  íìí P ë íì ëíì ìì ëìì ìê, ëì B ë
+ìì ëí ìì ëìì ìëê ìêí ëìë.  êëêì, ìê ììì íë CPU ì
+ììë ëíê ëì ëì ìì íìë ëíë ëê ììëë, íìí P ë ì ê
+(&B) ì, êëê ëì B ë ìë ê (2) ì êìê ìë ê ëìë ììëë.
+
+
+ëìí ììì ëëìë í ìë, RCU ììíìì ëì ììíëë.
+include/linux/rcupdate.h ì rcu_assign_pointer() ì rcu_dereference() ë
+ìêíìì.  ìê RCU ë íìíì íì íêì ìë ììë íêìë ëêë
+ìììì ìë ììë íêì ìêíê ìëìë ëêìì êìë ëìë ëìê
+ìê íìëë.
+
+ë ëì ìë ìíì "ìì ìêì" ìëììì ìêíìì.
+
+
+ìíë ììì
+-------------
+
+ëë-ëë ìíë ìììì ìëë ëìíê ìí ëìí ëìí ììì ëëìë
+ìë êëìëë ìëê, ìì ìê ëëë ëëìë íìë íëë.  ìëì ìëë
+ëìë:
+
+	q = READ_ONCE(a);
+	if (q) {
+		<ëìí ììì ëëì>  /* BUG: No data dependency!!! */
+		p = READ_ONCE(b);
+	}
+
+ìì ëìí ìììì ìëë CPU ê ëê ìêì êêë ììíì ìí ìëë ë
+ëëê ëë ìë ìë ìíë ìììì ììíê ëëì, ì ìëë ìíë ëë
+ëìíì ìê, ëë CPU ê b ëëíì ëë ìíëììì a ì ëë
+ìíëììëë ëì ëìí êë ë ìë ìê íëë.  ìêì ìëë íìíë
+ê:
+
+	q = READ_ONCE(a);
+	if (q) {
+		<ìê ëëì>
+		p = READ_ONCE(b);
+	}
+
+íìë, ìíì ìíëììì ììëì ììëë.  ì, ëì ìììì êì
+ëë-ìíì ìíë ìììì ììíë êììë ììê ìê-ëë-ë ìëìëë.
+
+	q = READ_ONCE(a);
+	if (q) {
+		WRITE_ONCE(b, p);
+	}
+
+ìíë ìììëì ëí ëë íìì ëëìëê ììëë.  êëëê íë,
+READ_ONCE() ë ìí êëíê ìëì ëëì êìí ëìì! READ_ONCE() ììë,
+ìíìëê ëì ëìêìì êêë ìëíë ììë 'a' ëëíì ëëë ëë 'a'
+ëëíì ëëì, 'b' ëì ìíìë ëë 'b' ëì ìíìì ìíí ëë ì
+ììëë.
+
+ìêë ëì ìëê, ìíìëê ëì 'a' ì êì íì 0ì ìëëê ìëí ì
+ìëë, ìì ììì "if" ëì ììì ëìê êì ììí í ìë ììëë:
+
+	q = a;
+	b = p;  /* BUG: Compiler and CPU can both reorder!!! */
+
+êëë READ_ONCE() ë ëëì ììíìì.
+
+ëìê êì "if" ëì ê ëëìì ëìí ìíìì ëí ììë êìíê ìì
+êìê ìì ì ììëë:
+
+	q = READ_ONCE(a);
+	if (q) {
+		barrier();
+		WRITE_ONCE(b, p);
+		do_something();
+	} else {
+		barrier();
+		WRITE_ONCE(b, p);
+		do_something_else();
+	}
+
+ìíêìë, íìì ìíìëëì ëì ììí ëëììë ìê ëìê êì
+ëêëëëë:
+
+	q = READ_ONCE(a);
+	barrier();
+	WRITE_ONCE(b, p);  /* BUG: No ordering vs. load from a!!! */
+	if (q) {
+		/* WRITE_ONCE(b, p); -- moved up, BUG!!! */
+		do_something();
+	} else {
+		/* WRITE_ONCE(b, p); -- moved up, BUG!!! */
+		do_something_else();
+	}
+
+ìì 'a' ììì ëëì 'b' ëì ìíì ìììë ìêì êêê ìê ëëì CPU
+ë ìëì ììë ëê ì ìê ëëë: ìêì êêë ëëì íìíëë, êëê
+ëë ìíìë ììíê ìëììê ë íì ììëë ìëììë ììíì íëë.
+ëëì, ì ììì ììë ìíê ìíìë smp_store_release() ì êì ëìì
+ëëë ëëìê íìíëë:
+
+	q = READ_ONCE(a);
+	if (q) {
+		smp_store_release(&b, p);
+		do_something();
+	} else {
+		smp_store_release(&b, p);
+		do_something_else();
+	}
+
+ëëë, ëìì ëëë ëëìê ìëë, ìë êìì ììë ìíì ìíëììëì
+ìë ëë ëìë, ìë ëì ëìê êì êìì ëìëëë:
+
+	q = READ_ONCE(a);
+	if (q) {
+		WRITE_ONCE(b, p);
+		do_something();
+	} else {
+		WRITE_ONCE(b, r);
+		do_something_else();
+	}
+
+ììì READ_ONCE() ë ìíìëê 'a' ì êì ìëíëë êì ëê ìí ììí
+íìíëë.
+
+ëí, ëì ëì 'q' ë êìê íë êì ëí ììíì íëë, êëì ììë
+ìíìëë ê êì ììíê ëëì íìí ìêêêë ììëë ì ììëë.
+ìë ëë:
+
+	q = READ_ONCE(a);
+	if (q % MAX) {
+		WRITE_ONCE(b, p);
+		do_something();
+	} else {
+		WRITE_ONCE(b, r);
+		do_something_else();
+	}
+
+ëì MAX ê 1 ë ììë ììëë, ìíìëë (q % MAX) ë 0ìë êì ìììê,
+ìì ìëë ìëì êì ëêëë ì ììëë:
+
+	q = READ_ONCE(a);
+	WRITE_ONCE(b, p);
+	do_something_else();
+
+ìëê ëë, CPU ë ëì 'a' ëëíì ëëì ëì 'b' ëì ìíì ììì ììë
+ììì íìê ìììëë.  barrier() ë ìêíê ìêìë, êê ëìì
+ìëëë.  ìê êêë ìëìê, ëëìë êê ëëëì ëíëë.  ëëì, ì
+ììë ììì íëë, MAX ê 1 ëë íëë êì, ëë ëìê êì ëëí íì
+íëë:
+
+	q = READ_ONCE(a);
+	BUILD_BUG_ON(MAX <= 1); /* Order load from a with store to b. */
+	if (q % MAX) {
+		WRITE_ONCE(b, p);
+		do_something();
+	} else {
+		WRITE_ONCE(b, r);
+		do_something_else();
+	}
+
+'b' ëì ìíìëì ììí ìë ëëì ììëìì.  ëì êêëì ëìíë,
+ììì ììêíë, ìíìëë ê ìíì ìíëììëì 'if' ë ëêìë
+ëììë ì ììëë.
+
+ëí ìì ìêë íêì ëë ììíì ìëë ììíì íëë.  ëìì ìë
+ëìë:
+
+	q = READ_ONCE(a);
+	if (q || 1 > 0)
+		WRITE_ONCE(b, 1);
+
+ìëì ìêì êìì ì ìê ëëì ìêì íì ììê ëëì, ìíìëë ì
+ìë ëìê êì ëêì ìíë ìììì ììëë ì ììëë:
+
+	q = READ_ONCE(a);
+	WRITE_ONCE(b, 1);
+
+ì ìë ìíìëê ìëë ììí ì ìëë êì ëëí íì í íìê ìëë
+ìì êìíëë.  ìê ìëììë ëíì, READ_ONCE() ê ìíìëìê ììì
+ëë ìíëììì ëí ìëë ëëëë êìíê íìë, ìíìëê ê êêë
+ììíëë êìíìë ììëë.
+
+ëìëìë, ìíë ìììì íëìì ìêíì -ììëë-.  ìê x ì y ê ë ë
+0 ìëë ìêêì êìëë êì íì ëêì ììë ëìêìëë:
+
+	CPU 0                     CPU 1
+	=======================   =======================
+	r1 = READ_ONCE(x);        r2 = READ_ONCE(y);
+	if (r1 > 0)               if (r2 > 0)
+	  WRITE_ONCE(y, 1);         WRITE_ONCE(x, 1);
+
+	assert(!(r1 == 1 && r2 == 1));
+
+ì ë CPU ììììë assert() ì ìêì êì ìì ì ìì êìëë.  íìë,
+ëì ìíë ìììì íëìì (ììëë êëì ììë) ëìíëë, ëìì CPU
+ê ìêëë êëë ìêì ëìí êëë:
+
+	CPU 2
+	=====================
+	WRITE_ONCE(x, 2);
+
+	assert(!(r1 == 2 && r2 == 1 && x == 2)); /* FAILS!!! */
+
+íìë ìíë ìììì íëìì ìêíì -ìê- ëëì, ìêì CPU ììê ìí
+ìëë íì assert() ì ìêì êìì êëë.  ìêì CPU ììê ììë ìíê
+ìíëë, CPU 0 ì CPU 1 ìëì ëëì ìíì ìì, "if" ë ëë ëìì
+smp_mb()ë ëìì íëë.  ë ëìêì, ììì ë CPU ììë ëì ììíê
+ììì ìììë íëë.
+
+ì ëêì ììë ëì ëëì ëì LB ì WWC ëíëì íìíëìëë:
+http://www.cl.cam.ac.uk/users/pes20/ppc-supplemental/test6.pdf ì ì ììí:
+https://www.cl.cam.ac.uk/~pes20/ppcmem/index.html.
+
+ììíìë:
+
+  (*) ìíë ìììì ìì ëëëì ëì ìíìëì ëí ììë ìììëë.
+      íìë, ê ìì ìë ììë ëìíì -ììëë-: ìì ëëì ëì ëëë
+      ìììë, ìì ìíìì ëì ìë êë ìììëì.  ìë ëë ííì
+      ììê íìíëë, smp_rmb() ë smp_wmb(), ëë ìì ìíìëê ëì
+      ëëë ììëë, smp_mb() ë ììíì í êëë.
+
+  (*) "if" ëì ì ëëìê êì ëììì ëìí ìíìëë ììíëë, ê
+      ìíìëì ê ìíì ìì smp_mb() ë ëêë smp_store_release() ë
+      ììíì ìíìë íë ììë ììë ëììì íëë.  ìíìë ììíë
+      ì êìì barrier() ë ëìí ìë ìê ëëì "if" ëì ì ëëìì
+      ììììì barrier() ë ëë êëìëë ìëíì ììì ìì ëìê
+      ëëëë.
+
+  (*) ìíë ìììì ìì ëëì ëì ìíì ììì ìì íëì ëíì
+      ìêêêë íìë íë, ì ìêêêë ìì ëëì êêëìì íëë.
+      ëì ìíìëê ìê êêë ììíë ìì ì ìëë, ììë ììí
+      íëëì êëë.  READ_ONCE() ì WRITE_ONCE() ê ììì ìê êêë
+      ììíëë ëìì ë ì ììë ì ììíì íëë.
+
+  (*) ìíë ìììì ìíì ìíìëê ìêêêë ììëëë êì ëìì
+      íëë.  ìíë ìììì ìëìì ìê íëë ìì êì READ_ONCE() ë
+      atomic{,64}_read() ê ëìì ì ì ììëë.  ë ëì ìëë ìíì
+      "ìíìë ëëì" ììì ìêíìê ëëëë.
+
+  (*) ìíë ìììì ëí ëë íìì ëëìëê ììëë.
+
+  (*) ìíë ìììì íëìì ìêíì -ììëë-. íëìì íìíëë,
+      smp_mb() ë ììíìì.
+
+
+SMP ëëì ìëìê
+--------------------
+
+CPU ê ìíììì í ëìë ìë íìì ëëë ëëìë íì ìì ëì
+ììëììë íëë.  ììíê ìì ëìì ëíë êì íì ìëë ìëíëë.
+
+ëì ëëìëì íëìì ìììëë ëëëì ëë íìì ëëìëêë ìì
+ëììë, ëì ëëìëë ìì ëìëë.  ACQUIRE ëëìë RELEASE ëëìì
+ìì ëìëëë, ëì ëëìë ííí ëë ëëìëêë ìì ëì ì ììëë.
+ìê ëëìë ëìí ììì ëëìë ìíë ììì, ACQUIRE ëëì, RELEASE
+ëëì, ìê ëëì, ëë ëì ëëìì ìì ëìëë.  ëìíê ìê ëëìë
+ìíë ììì, ëë ëìí ììì ëëìë ìê ëëìë ACQUIRE ëëì,
+RELEASE ëëì, ëë ëì ëëìì ìì ëìëë:
+
+	CPU 1		      CPU 2
+	===============	      ===============
+	WRITE_ONCE(a, 1);
+	<ìê ëëì>
+	WRITE_ONCE(b, 2);     x = READ_ONCE(b);
+			      <ìê ëëì>
+			      y = READ_ONCE(a);
+
+ëë:
+
+	CPU 1		      CPU 2
+	===============	      ===============================
+	a = 1;
+	<ìê ëëì>
+	WRITE_ONCE(b, &a);    x = READ_ONCE(b);
+			      <ëìí ììì ëëì>
+			      y = *x;
+
+ëë:
+
+	CPU 1		      CPU 2
+	===============	      ===============================
+	r1 = READ_ONCE(y);
+	<ëì ëëì>
+	WRITE_ONCE(y, 1);     if (r2 = READ_ONCE(x)) {
+			         <implicit control dependency>
+			         WRITE_ONCE(y, 1);
+			      }
+
+	assert(r1 == 0 || r2 == 0);
+
+êëììë, ìê ëëìë "ë ìí" íìì ì ììë íì ììíì íëë.
+
+[!] ìê ëëì ììì ìíì ìíëììì ìëììë ìê ëëìë ëìí
+ììì ëëì ëì ëë ìíëììê ëìë êìê, ëëë ëìêììëë:
+
+	CPU 1                               CPU 2
+	===================                 ===================
+	WRITE_ONCE(a, 1);    }----   --->{  v = READ_ONCE(c);
+	WRITE_ONCE(b, 2);    }    \ /    {  w = READ_ONCE(d);
+	<ìê ëëì>              \        <ìê ëëì>
+	WRITE_ONCE(c, 3);    }    / \    {  x = READ_ONCE(a);
+	WRITE_ONCE(d, 4);    }----   --->{  y = READ_ONCE(b);
+
+
+ëëë ëëì ìíìì ì
+-------------------------
+
+ìì, ìê ëëìëì ìíì ìíëììëì ëëì ìì ììêë ëìíëë.
+ìëì ìëì ìëíëì ëìì:
+
+	CPU 1
+	=======================
+	STORE A = 1
+	STORE B = 2
+	STORE C = 3
+	<ìê ëëì>
+	STORE D = 4
+	STORE E = 5
+
+ì ìëì ìëíëì ìêì ëëë ììíì ììíì ëëì ììëì
+ììëëëë ìì ìë, ìí { STORE A, STORE B, STORE C } ê ìì
+ìììëëëì ìì ìë, ìí { STORE D, STORE E } ëë ëì ììë êìë
+ëìëë ìëëëë:
+
+	+-------+       :      :
+	|       |       +------+
+	|       |------>| C=3  |     }     /\
+	|       |  :    +------+     }-----  \  -----> ììíì ëëì ììì
+	|       |  :    | A=1  |     }        \/       ëììë ìëíë
+	|       |  :    +------+     }
+	| CPU 1 |  :    | B=2  |     }
+	|       |       +------+     }
+	|       |   wwwwwwwwwwwwwwww }   <--- ìêì ìê ëëìê ëëì ìì
+	|       |       +------+     }        ëë ìíìê ìíì ìíìê
+	|       |  :    | E=5  |     }        ëìê ìì ëëë ììíì
+	|       |  :    +------+     }        ìëëëë íëë
+	|       |------>| D=4  |     }
+	|       |       +------+
+	+-------+       :      :
+	                   |
+	                   | CPU 1 ì ìí ëëë ììíì ìëëë
+	                   | ìëì ìíì ìíëììë
+	                   V
+
+
+ëì, ëìí ììì ëëìë ëìí ììì ëë ìíëììëì ëëì ìì
+ììêë ëìíëë.  ëì ìëì ìëíëì ëìì:
+
+	CPU 1			CPU 2
+	=======================	=======================
+		{ B = 7; X = 9; Y = 8; C = &Y }
+	STORE A = 1
+	STORE B = 2
+	<ìê ëëì>
+	STORE C = &B		LOAD X
+	STORE D = 4		LOAD C (gets &B)
+				LOAD *C (reads B)
+
+ìêì ëëë êìì ìëë, CPU 1 ì ìê ëëììë ëêíê CPU 2 ë CPU 1
+ì ìëíëì ììí ëììì ììë ììíê ëëë:
+
+	+-------+       :      :                :       :
+	|       |       +------+                +-------+  | CPU 2 ì ììëë
+	|       |------>| B=2  |-----       --->| Y->8  |  | ìëìí ìëí
+	|       |  :    +------+     \          +-------+  | ìíì
+	| CPU 1 |  :    | A=1  |      \     --->| C->&Y |  V
+	|       |       +------+       |        +-------+
+	|       |   wwwwwwwwwwwwwwww   |        :       :
+	|       |       +------+       |        :       :
+	|       |  :    | C=&B |---    |        :       :       +-------+
+	|       |  :    +------+   \   |        +-------+       |       |
+	|       |------>| D=4  |    ----------->| C->&B |------>|       |
+	|       |       +------+       |        +-------+       |       |
+	+-------+       :      :       |        :       :       |       |
+	                               |        :       :       |       |
+	                               |        :       :       | CPU 2 |
+	                               |        +-------+       |       |
+	    ëëí ìëë        --->  |        | B->7  |------>|       |
+	    B ì ê ìì (!)           |        +-------+       |       |
+	                               |        :       :       |       |
+	                               |        +-------+       |       |
+	    ëëë X ì êì    --->    \       | X->9  |------>|       |
+	    B ì ììì êì             \      +-------+       |       |
+	    ììíê íì íë            ----->| B->2  |       +-------+
+	                                        +-------+
+	                                        :       :
+
+
+ìì ììì, CPU 2 ë (B ì êì ë) *C ì ê ìêê C ì LOAD ëì ììììë
+B ê 7 ìëë êêë ììëë.
+
+íìë, ëì ëìí ììì ëëìê C ì ëëì *C (ì, B) ììì ììëë:
+
+	CPU 1			CPU 2
+	=======================	=======================
+		{ B = 7; X = 9; Y = 8; C = &Y }
+	STORE A = 1
+	STORE B = 2
+	<ìê ëëì>
+	STORE C = &B		LOAD X
+	STORE D = 4		LOAD C (gets &B)
+				<ëìí ììì ëëì>
+				LOAD *C (reads B)
+
+ëìê êì ëëë:
+
+	+-------+       :      :                :       :
+	|       |       +------+                +-------+
+	|       |------>| B=2  |-----       --->| Y->8  |
+	|       |  :    +------+     \          +-------+
+	| CPU 1 |  :    | A=1  |      \     --->| C->&Y |
+	|       |       +------+       |        +-------+
+	|       |   wwwwwwwwwwwwwwww   |        :       :
+	|       |       +------+       |        :       :
+	|       |  :    | C=&B |---    |        :       :       +-------+
+	|       |  :    +------+   \   |        +-------+       |       |
+	|       |------>| D=4  |    ----------->| C->&B |------>|       |
+	|       |       +------+       |        +-------+       |       |
+	+-------+       :      :       |        :       :       |       |
+	                               |        :       :       |       |
+	                               |        :       :       | CPU 2 |
+	                               |        +-------+       |       |
+	                               |        | X->9  |------>|       |
+	                               |        +-------+       |       |
+	  C ì ìíì ìì       --->   \   ddddddddddddddddd   |       |
+	  ëë ìëí êêê             \      +-------+       |       |
+	  ëì ëëìê                   ----->| B->2  |------>|       |
+	  ëìê êìíë                       +-------+       |       |
+	                                        :       :       +-------+
+
+
+ìëì, ìê ëëìë ëë ìíëììëìì ëëì ìì ììêë ëìíëë.
+ìëì ìëì ìëíë ëìë:
+
+	CPU 1			CPU 2
+	=======================	=======================
+		{ A = 0, B = 9 }
+	STORE A=1
+	<ìê ëëì>
+	STORE B=2
+				LOAD B
+				LOAD A
+
+CPU 1 ì ìê ëëìë ììë, ëëë êìì ìëë CPU 2 ë CPU 1 ìì ííì
+ìëíì êêë ëììì ììë ììíê ëëë.
+
+	+-------+       :      :                :       :
+	|       |       +------+                +-------+
+	|       |------>| A=1  |------      --->| A->0  |
+	|       |       +------+      \         +-------+
+	| CPU 1 |   wwwwwwwwwwwwwwww   \    --->| B->9  |
+	|       |       +------+        |       +-------+
+	|       |------>| B=2  |---     |       :       :
+	|       |       +------+   \    |       :       :       +-------+
+	+-------+       :      :    \   |       +-------+       |       |
+	                             ---------->| B->2  |------>|       |
+	                                |       +-------+       | CPU 2 |
+	                                |       | A->0  |------>|       |
+	                                |       +-------+       |       |
+	                                |       :       :       +-------+
+	                                 \      :       :
+	                                  \     +-------+
+	                                   ---->| A->1  |
+	                                        +-------+
+	                                        :       :
+
+
+íìë, ëì ìê ëëìê B ì ëëì A ì ëë ììì ììíëë:
+
+	CPU 1			CPU 2
+	=======================	=======================
+		{ A = 0, B = 9 }
+	STORE A=1
+	<ìê ëëì>
+	STORE B=2
+				LOAD B
+				<ìê ëëì>
+				LOAD A
+
+CPU 1 ì ìí ëëìì ëëì ììê CPU 2 ìë êëë ììëëë:
+
+	+-------+       :      :                :       :
+	|       |       +------+                +-------+
+	|       |------>| A=1  |------      --->| A->0  |
+	|       |       +------+      \         +-------+
+	| CPU 1 |   wwwwwwwwwwwwwwww   \    --->| B->9  |
+	|       |       +------+        |       +-------+
+	|       |------>| B=2  |---     |       :       :
+	|       |       +------+   \    |       :       :       +-------+
+	+-------+       :      :    \   |       +-------+       |       |
+	                             ---------->| B->2  |------>|       |
+	                                |       +-------+       | CPU 2 |
+	                                |       :       :       |       |
+	                                |       :       :       |       |
+	  ìêì ìê ëëìë   ---->   \  rrrrrrrrrrrrrrrrr   |       |
+	  B ì ìíì ììì              \     +-------+       |       |
+	  ëë êêë CPU 2 ì             ---->| A->1  |------>|       |
+	  ëìëë íë                         +-------+       |       |
+	                                        :       :       +-------+
+
+
+ë ìëí ìëì ìí, A ì ëëê ìê ëëì ìê ëì ììë ìëê ëì
+ìêí ëìë:
+
+	CPU 1			CPU 2
+	=======================	=======================
+		{ A = 0, B = 9 }
+	STORE A=1
+	<ìê ëëì>
+	STORE B=2
+				LOAD B
+				LOAD A [first load of A]
+				<ìê ëëì>
+				LOAD A [second load of A]
+
+A ì ëë ëêê ëë B ì ëë ìíì ììë, ìë ëë êì ììì ì
+ììëë:
+
+	+-------+       :      :                :       :
+	|       |       +------+                +-------+
+	|       |------>| A=1  |------      --->| A->0  |
+	|       |       +------+      \         +-------+
+	| CPU 1 |   wwwwwwwwwwwwwwww   \    --->| B->9  |
+	|       |       +------+        |       +-------+
+	|       |------>| B=2  |---     |       :       :
+	|       |       +------+   \    |       :       :       +-------+
+	+-------+       :      :    \   |       +-------+       |       |
+	                             ---------->| B->2  |------>|       |
+	                                |       +-------+       | CPU 2 |
+	                                |       :       :       |       |
+	                                |       :       :       |       |
+	                                |       +-------+       |       |
+	                                |       | A->0  |------>| 1st   |
+	                                |       +-------+       |       |
+	  ìêì ìê ëëìë   ---->   \  rrrrrrrrrrrrrrrrr   |       |
+	  B ì ìíì ììì              \     +-------+       |       |
+	  ëë êêë CPU 2 ì             ---->| A->1  |------>| 2nd   |
+	  ëìëë íë                         +-------+       |       |
+	                                        :       :       +-------+
+
+
+íìë CPU 1 ììì A ìëìíë ìê ëëìê ìëëê ììë ëì ìë ìê
+íëë:
+
+	+-------+       :      :                :       :
+	|       |       +------+                +-------+
+	|       |------>| A=1  |------      --->| A->0  |
+	|       |       +------+      \         +-------+
+	| CPU 1 |   wwwwwwwwwwwwwwww   \    --->| B->9  |
+	|       |       +------+        |       +-------+
+	|       |------>| B=2  |---     |       :       :
+	|       |       +------+   \    |       :       :       +-------+
+	+-------+       :      :    \   |       +-------+       |       |
+	                             ---------->| B->2  |------>|       |
+	                                |       +-------+       | CPU 2 |
+	                                |       :       :       |       |
+	                                 \      :       :       |       |
+	                                  \     +-------+       |       |
+	                                   ---->| A->1  |------>| 1st   |
+	                                        +-------+       |       |
+	                                    rrrrrrrrrrrrrrrrr   |       |
+	                                        +-------+       |       |
+	                                        | A->1  |------>| 2nd   |
+	                                        +-------+       |       |
+	                                        :       :       +-------+
+
+
+ìêì ëìëë ê, ëì B ì ëëê B == 2 ëë êêë ëëë, A ìì ëëì
+ëëë íì A == 1 ì ëê ë êìëë êëë.  A ìì ìëì ëëìë êë
+ëìì ììëë; A == 0 ìêë A == 1 ì êêë ëê ë êìëë.
+
+
+ìê ëëë ëëì VS ëë ìííëìì
+---------------------------------------
+
+ëì CPUëì ëëë ììììë íëë: ëëëìì ìë ëìíë ëëíì íê
+ëì ììì íê, ììë íë ëìíë ëëíë ììíëìì ìì ëëì
+ììëëë ëë ëë ììì ìì ëìê ììëê ìì ìì ë, ê ëìíë
+ëëíëë.  ìë ìí ìì ëë ììíëìì CPU ê ìë ê êì êìê ìê
+ëëì ìì ìëëëë.
+
+íë CPU ë ììëë ê êì íìì ììëë ììì ëì ìë ìëë - íë
+ëë ììíëìì ê ëëìë ìíëêë íì ì ìêì - , ì ëìë ê êì
+ëëêë ëìì ììì ìí ììì ëìë ì ììëë.
+
+ëìì ìêí ëìë:
+
+	CPU 1			CPU 2
+	=======================	=======================
+				LOAD B
+				DIVIDE		} ëëê ëëì ìëììë
+				DIVIDE		} ê ìêì íìë íëë
+				LOAD A
+
+ë ìëê ë ì ììëë:
+
+	                                        :       :       +-------+
+	                                        +-------+       |       |
+	                                    --->| B->2  |------>|       |
+	                                        +-------+       | CPU 2 |
+	                                        :       :DIVIDE |       |
+	                                        +-------+       |       |
+	ëëê íëë ëì       --->       --->| A->0  |~~~~   |       |
+	CPU ë A ì LOAD ë                     +-------+   ~   |       |
+	ììíë                                :       :   ~   |       |
+	                                        :       :DIVIDE |       |
+	                                        :       :   ~   |       |
+	ëëêê ëëë       --->     --->     :       :   ~-->|       |
+	CPU ë íë LOAD ë                     :       :       |       |
+	ìê ìëíë                           :       :       +-------+
+
+
+ìê ëëìë ëìí ììì ëëìë ëëì ëë ììì ëëëë:
+
+	CPU 1			CPU 2
+	=======================	=======================
+				LOAD B
+				DIVIDE
+				DIVIDE
+				<ìê ëëì>
+				LOAD A
+
+ìììë ìììë êì ììë ëëìì íìì ëëì íë êì ììì
+êííëëë.  ëì íë ëëë ììì ëíê ììëë, ìììë ììëìë
+êì ììëëë:
+
+	                                        :       :       +-------+
+	                                        +-------+       |       |
+	                                    --->| B->2  |------>|       |
+	                                        +-------+       | CPU 2 |
+	                                        :       :DIVIDE |       |
+	                                        +-------+       |       |
+	ëëê íëë ëì       --->       --->| A->0  |~~~~   |       |
+	CPU ë A ì LOAD ë                     +-------+   ~   |       |
+	ììíë                                :       :   ~   |       |
+	                                        :       :DIVIDE |       |
+	                                        :       :   ~   |       |
+	                                        :       :   ~   |       |
+	                                    rrrrrrrrrrrrrrrr~   |       |
+	                                        :       :   ~   |       |
+	                                        :       :   ~-->|       |
+	                                        :       :       |       |
+	                                        :       :       +-------+
+
+
+íìë ëë CPU ìì ìëìíë ëííê ììëë, ê ììì ëííëê ê êì
+ëì ìíìëë:
+
+	                                        :       :       +-------+
+	                                        +-------+       |       |
+	                                    --->| B->2  |------>|       |
+	                                        +-------+       | CPU 2 |
+	                                        :       :DIVIDE |       |
+	                                        +-------+       |       |
+	ëëê íëë ëì       --->       --->| A->0  |~~~~   |       |
+	CPU ë A ì LOAD ë                     +-------+   ~   |       |
+	ììíë                                :       :   ~   |       |
+	                                        :       :DIVIDE |       |
+	                                        :       :   ~   |       |
+	                                        :       :   ~   |       |
+	                                    rrrrrrrrrrrrrrrrr   |       |
+	                                        +-------+       |       |
+	ììì ëìì ëíí ëê    --->   --->| A->1  |------>|       |
+	ìëìíë êì ëì ìíìë           +-------+       |       |
+	                                        :       :       +-------+
+
+
+íëì
+------
+
+íëì(transitivity)ì ìì ìíí ììíìì íì ìêëìë ìë, ìì
+ëìêì ëí ìëí ìêìì êëìëë.  ëìì ìë
+íëìì ëììëë:
+
+	CPU 1			CPU 2			CPU 3
+	=======================	=======================	=======================
+		{ X = 0, Y = 0 }
+	STORE X=1		LOAD X			STORE Y=1
+				<ëì ëëì>		<ëì ëëì>
+				LOAD Y			LOAD X
+
+CPU 2 ì X ëëê 1ì ëííê Y ëëê 0ì ëííëê íëìë.  ìë CPU 2 ì
+X ëëë CPU 1 ì X ìíì ëì ìëììê CPU 2 ì Y ëëë CPU 3 ì Y ìíì
+ìì ìëìììì ìëíëë.  êë "CPU 3 ì X ëëë 0ì ëíí ì ìëì?"
+
+CPU 2 ì X ëëë CPU 1 ì ìíì ìíì ìëìììë, CPU 3 ì X ëëë 1ì
+ëííëê ìììëìëë.  ìë ìêì íëìì í ììëë: CPU A ìì ìíë
+ëëê CPU B ììì êì ëìì ëí ëëë ëëëëë, CPU A ì ëëë CPU B
+ì ëëê ëëì êê êêë ê ìíì êì ëëìì ëëìì íëë.
+
+ëëì ìëìì ëì ëëìì ììì íëìì ëìí ìëë.  ëëì, ìì
+ììì CPU 2 ì X ëëê 1ì, Y ëëë 0ì ëííëë, CPU 3 ì X ëëë ëëì
+1ì ëííëë.
+
+íìë, ìêë ìê ëëìì ëíìë íëìì ëìëì -ììëë-.  ìë ëì,
+ìì ììì CPU 2 ì ëì ëëìê ìëìë ìê ëëìë ëë êìë ìêí
+ëìë:
+
+	CPU 1			CPU 2			CPU 3
+	=======================	=======================	=======================
+		{ X = 0, Y = 0 }
+	STORE X=1		LOAD X			STORE Y=1
+				<ìê ëëì>		<ëì ëëì>
+				LOAD Y			LOAD X
+
+ì ìëë íëìì ìíì ììëë: ì ìììë, CPU 2 ì X ëëê 1ì
+ëííê, Y ëëë 0ì ëííìë CPU 3 ì X ëëê 0ì ëííë êë ììí
+íëììëë.
+
+CPU 2 ì ìê ëëìê ììì ìêë ììë ëììë, CPU 1 ì ìíìë
+ëììëêë ëìí ì ìëëê íììëë.  ëëì, ì ììê CPU 1 ê CPU 2
+ê ëíë ììë êìíë ììíìì ëìíëë, CPU 2 ë CPU 1 ì ì êì ì
+ëë ìêí ì ìì êìëë.  ëëì CPU 1 ê CPU 2 ì ìêìë ìíë ììë
+ëë CPU ê ëìí ì ìëë íê ìí ëì ëëìê íìíëë.
+
+ëì ëëìë "êëë íëì"ì ìêíì, ëë CPU ëì ìíëììëì ììì
+ëìíê í êìëë.  ëë, release-acquire ìíì ëì "ëì íëì" ëì
+ìêíì, íë ìíì ììë CPU ëëì íë ìììëì ìíë ììì ëìíì
+ëìëëë.  ìë ëì, ìêìë Herman Hollerith ì C ìëë ëë:
+
+	int u, v, x, y, z;
+
+	void cpu0(void)
+	{
+		r0 = smp_load_acquire(&x);
+		WRITE_ONCE(u, 1);
+		smp_store_release(&y, 1);
+	}
+
+	void cpu1(void)
+	{
+		r1 = smp_load_acquire(&y);
+		r4 = READ_ONCE(v);
+		r5 = READ_ONCE(u);
+		smp_store_release(&z, 1);
+	}
+
+	void cpu2(void)
+	{
+		r2 = smp_load_acquire(&z);
+		smp_store_release(&x, 1);
+	}
+
+	void cpu3(void)
+	{
+		WRITE_ONCE(v, 1);
+		smp_mb();
+		r3 = READ_ONCE(u);
+	}
+
+cpu0(), cpu1(), êëê cpu2() ë smp_store_release()/smp_load_acquire() ìì
+ìêì íí ëì íëìì ëìíê ììëë, ëìê êì êêë ëìì ìì
+êëë:
+
+	r0 == 1 && r1 == 1 && r2 == 1
+
+ëìêì, cpu0() ì cpu1() ììì release-acquire êêë cpu0() ì ìêë
+ëìë íëë, ëìê êì êêë ëìì ìì êëë:
+
+	r1 == 1 && r5 == 0
+
+íìë, release-acquire íëìì ëìí CPU ëìë ììëëë cpu3() ìë
+ììëì ììëë.  ëëì, ëìê êì êêê êëíëë:
+
+	r0 == 0 && r1 == 1 && r2 == 1 && r3 == 0 && r4 == 0
+
+ëìíê, ëìê êì êêë êëíëë:
+
+	r0 == 0 && r1 == 1 && r2 == 1 && r3 == 0 && r4 == 0 && r5 == 1
+
+cpu0(), cpu1(), êëê cpu2() ê êìì ìêì ìêë ììëë ëê ëìë,
+release-acquire ììì êìëì ìì CPU ëì ê ììì ìêì êì ìë
+ììëë.  ìë ìêì smp_load_acquire() ì smp_store_release() ë êííëë
+ììëë ìíë ëëë ëëì ììíëìëì ììì ìíìëì ìíì ëëëì
+íì ììì íìë ìëë ìììì êìíëë.  ì ëì cpu3() ë cpu0() ì u
+ìì ìíìë cpu1() ì v ëëíì ëë ìíì ììë êìë ë ì ìëë
+ëìëë, cpu0() ì cpu1() ì ì ë ìíëììì ìëë ììëë ììëìì
+ëìíìë ëìì.
+
+íìë, smp_load_acquire() ë ëìì ìëì ëë êìíìê ëëëë.  ííë,
+ì íìë ëìí êêì ììë ììëë ììëë.  ìêì ìë íìí êì ìí
+êììë ëìíì -ììëë-.  ëëì, ëìê êì êêë êëíëë:
+
+	r0 == 0 && r1 == 0 && r2 == 0 && r5 == 0
+
+ìë êêë ìë êë ìëì ëì ìë êìì ììì ìêì ììíììë ììë
+ì ììì êìí ëìê ëëëë.
+
+ëì ëíìë, ëìì ìëê êëë íëìì íìë íëë, ëì ëëìë
+ììíììì.
+
+
+====================
+ëìì ìë ëëìë
+====================
+
+ëëì ìëì ìë ëë ìììë ëìíë ëìí ëëìëì êìê ììëë:
+
+  (*) ìíìë ëëì.
+
+  (*) CPU ëëë ëëì.
+
+  (*) MMIO ìê ëëì.
+
+
+ìíìë ëëì
+---------------
+
+ëëì ìëì ìíìëê ëëë ìììë íììì ëë ììë ìêëëë êì
+ëììë ëììì ìíìë ëëìë êìê ììëë:
+
+	barrier();
+
+ìê ëì ëëììëë -- barrier() ì ìê-ìê ë ìê-ìê ëìì ììëë.
+íìë, READ_ONCE() ì WRITE_ONCE() ë READ_ONCE() ëë WRITE_ONCE() ë íìë
+ìììëì ëíìë ëìíë barrier() ì ìíë ííë ë ì ììëë.
+
+barrier() íìë ëìê êì íêë êìëë:
+
+ (*) ìíìëê barrier() ëì ìììëì barrier() ìì ìììëë ëì
+     ëìíì ëíê íëë.  ìììë ëìëìë, ìíëí íëë ìëì
+     ìíëíë ìë ììì íìì ììê ìí ììë ì ììëë.
+
+ (*) ëí ëìì, ìíìëê ëí ìêì ììë ëìë ë ìíëììëë
+     ëëíëë íëë.
+
+READ_ONCE() ì WRITE_ONCE() íìë ìê ìëë ìëììë ëì ììë ëìì
+ìëììë ìëìì ì ìë ëë ììíë ëìëë.  ìë ëì ììíë ìë
+ëêì ëìëë ëìê êìëë:
+
+ (*) ìíìëë êì ëìì ëí ëëì ìíìë ìëì í ì ììë, ìë
+     êììë êì ëìì ëí ëëëì ìëìí ìë ììëë.  ì ëì ëìì
+     ìëê:
+
+	a[0] = x;
+	a[1] = x;
+
+     x ì ìì êì a[1] ì, ì êì a[0] ì ìê í ì ìëë êìëë.
+     ìíìëë CPU ë ìë ìì ëíê íëë ëìê êì íì íëë:
+
+	a[0] = READ_ONCE(x);
+	a[1] = READ_ONCE(x);
+
+     êëí ìëíì, READ_ONCE() ì WRITE_ONCE() ë ìë CPU ìì íëì
+     ëìì êíìë ìììëì ìì ìêìì ìêíëë.
+
+ (*) ìíìëë êì ëìì ëí ìììì ëëëì ëíí ì ììëë.  êë
+     ëí ìììë ìíìëë ëìì ìëë:
+
+	while (tmp = a)
+		do_something_with(tmp);
+
+     ëìê êì, ìê ìëë ìëììë ëì ëìë, êëìì ìëì ìí ëì
+     ìë ëíìë "ììí" í ì ììëë:
+
+	if (tmp = a)
+		for (;;)
+			do_something_with(tmp);
+
+     ìíìëê ìë ìì íì ëíê íëë READ_ONCE() ë ììíìì:
+
+	while (tmp = READ_ONCE(a))
+		do_something_with(tmp);
+
+ (*) ìíìëë, ìë ëì ëììí ììëì ëì ìíìëê ëë ëìíë
+     ëììíì ëì ì ìë êì, ëìë ëì ëëí ì ììëë.  ëëì
+     ìíìëë ìì ììì ëì 'tmp' ë ììí í ì ììëë:
+
+	while (tmp = a)
+		do_something_with(tmp);
+
+     ì ìëë ëìê êì ìê ìëëììë ìëíìë ëììì ììíë
+     êìì ìëìì ìëë ëë ì ììëë:
+
+	while (a)
+		do_something_with(a);
+
+     ìë ëì, ììíë ì ìëë íë ëìê ëë CPU ì ìí "while" ëê
+     do_something_with() íì ììì ëëì do_something_with() ì 0ì ëê
+     ìë ììëë.
+
+     ìëìë, ìíìëê êë ìì íëê ëê ìí READ_ONCE() ë ììíìì:
+
+	while (tmp = READ_ONCE(a))
+		do_something_with(tmp);
+
+     ëììíê ëìí ìíì êë êì, ìíìëë tmp ë ìíì ììíë ìë
+     ììëë.  ì ììê, íì ëì ììëìëë ëë ìëíëê ëìë ëì
+     ììëìë ìììëë.  êëê íëê ìê ìëë ìëììë ììíê
+     ëëì, ììíì ìì êììë ìíìëìê ìì ìëìì íëë.
+
+ (*) ìíìëë ê êì ëììì ìê ìëë ëëë ìì ìí ìë ììëë.
+     ìë ëì, ëìì ìëë ëì 'a' ì êì íì 0ìì ìëí ì ìëë:
+
+	while (tmp = a)
+		do_something_with(tmp);
+
+     ìëê ììí íëë ì ììëë:
+
+	do { } while (0);
+
+     ì ëíì ìê ìëë ìëììë ëìì ëëë ëëì ëëìë ìêíê
+     ëëìëë.  ëìë ìíìëê 'a' ì êì ìëìí íëê íìì CPU íë
+     ëìëë êì ììì ìëì íëëë ììëë.  ëì ëì 'a' ê êìëì
+     ìëë, ìíìëì ìëì íë êì ëêëë.  ìíìëë ê ììì
+     ìêíë êëí ëì êì ìê ìì ëíì ìíìëìê ìëê ìí
+     READ_ONCE() ë ììíìì:
+
+	while (tmp = READ_ONCE(a))
+		do_something_with(tmp);
+
+     íìë ìíìëë READ_ONCE() ëì ëìë êì ëíìë ëêì ëê ììì
+     êìíìì.  ìë ëì, ëìì ìëìì MAX ë ììëê ëíëë, 1ì êì
+     êëëê íëìë:
+
+	while ((tmp = READ_ONCE(a)) % MAX)
+		do_something_with(tmp);
+
+     ìëê ëë ìíìëë MAX ë êìê ìíëë "%" ìíëìíì êêê íì
+     0ìëë êì ìê ëê, ìíìëê ìëë ììíì ìë êìë ììí íë
+     êì íìíê ëëë.  ('a' ëìì ëëë ììí ìëììêëë.)
+
+ (*) ëìíê, ìíìëë ëìê ìë ììíë íë êì êìê ìëë êì
+     ìë ìíì ììë ìêí ì ììëë.  ìëìë, ìíìëë íìì CPU
+     ëì ê ëìì êì ìë ìëì íëì ììëê ìêíì ìíìëê êìë
+     ëìì ëí ìëë ìì íê ëëë.  ìë ëì, ëìê êì êìê
+     ììëë:
+
+	a = 0;
+	/* ëì a ì ìíìë íì ìë ìë. */
+	a = 0;
+
+     ìíìëë ëì 'a' ì êì ìë 0ìëë êì ìê, ëëì ëëì ìíìë
+     ììí êëë.  ëì ëë CPU ê ê ìì ëì 'a' ì ëë êì ìëë
+     íëí êêê ëì êëë.
+
+     ìíìëê êë ìëë ììì íì ìëë WRITE_ONCE() ë ììíìì:
+
+	WRITE_ONCE(a, 0);
+	/* ëì a ì ìíìë íë ìë. */
+	WRITE_ONCE(a, 0);
+
+ (*) ìíìëë íì ëëê íì ììë ëëë ìììëì ìëì í ì
+     ììëë.  ìë ëì, ëìì íëìì ëë ìëì ìíëí íëë ììì
+     ìíììì ìêí ëìë:
+
+	void process_level(void)
+	{
+		msg = get_message();
+		flag = true;
+	}
+
+	void interrupt_handler(void)
+	{
+		if (flag)
+			process_message(msg);
+	}
+
+     ìíìëê process_level() ì ëìê êì ìëë ëííë êì ëì ìëì
+     ìêì ìê, ììë, ì ëíì ìêìëëììëë íëí ìíìëë:
+
+	void process_level(void)
+	{
+		flag = true;
+		msg = get_message();
+	}
+
+     ì ëêì ëì ììì ìíëíê ëìíëë, interrupt_handler() ë ìëë
+     ì ì ìë ëììë ëì ìë ììëë.  ìê ëê ìí ëìê êì
+     WRITE_ONCE() ë ììíìì:
+
+	void process_level(void)
+	{
+		WRITE_ONCE(msg, get_message());
+		WRITE_ONCE(flag, true);
+	}
+
+	void interrupt_handler(void)
+	{
+		if (READ_ONCE(flag))
+			process_message(READ_ONCE(msg));
+	}
+
+     interrupt_handler() ìììë ììë ìíëíë NMI ì êì ìíëí íëë
+     ìì 'flag' ì 'msg' ì ìêíë ëëë ëìêì ìíëí ë ì ìëë
+     READ_ONCE() ì WRITE_ONCE() ëíëì ììíì íì êìí ëìì.  ëì
+     êë êëìì ìëë, interrupt_handler() ìììë ëìí ëìì ìëëë
+     READ_ONCE() ì WRITE_ONCE() ë íìì ììëë.  (êëì ëëì ìëìì
+     ììë ìíëíë ëí ì ììëì ììë êìí ëìì, ììë, ìë
+     ìíëí íëëê ìíëíê íìíë ìë ëííë WARN_ONCE() ê
+     ëìíëë.)
+
+     ìíìëë READ_ONCE() ì WRITE_ONCE() ìíì READ_ONCE() ë WRITE_ONCE(),
+     barrier(), ëë ëìí êëì ëê ìì ìì ìëëì ììì êì êìíì
+     íëë.
+
+     ì íêë barrier() ë ííìë ëë ì ììë, READ_ONCE() ì
+     WRITE_ONCE() ê ì ë ìë ëì ìíìëë: READ_ONCE() ì WRITE_ONCE()ë
+     ìíìëì ììì ëëë ììì ëíìë ììí êëìì ìëë íìë,
+     barrier() ë ìíìëê ìêêì êêì ëììíì ììí ëì ëë ëëë
+     ììì êì ëëì íê íê ëëìëë.  ëë, ìíìëë READ_ONCE() ì
+     WRITE_ONCE() ê ììë ììë ìììëë, CPU ë ëë êëì ìêìëì.
+
+ (*) ìíìëë ëìì ìììì êì ëììì ìíìë ëìíë ìë ììëë:
+
+	if (a)
+		b = a;
+	else
+		b = 42;
+
+     ìíìëë ìëì êì ììíë ëëìë ìì êëë:
+
+	b = 42;
+	if (a)
+		b = a;
+
+     ìê ìëë ìëììë ì ììíë ììí ë ìëë ëëì êìë
+     ìììëë.  íìë ìíêêë, ëììì ìë ìëììë ì ììíë ëë
+     CPU ê 'b' ë ëëí ë, -- 'a' ê 0ì ìëëë -- êìì ê, 42ë ëê
+     ëë êìë êëíê íëë.  ìê ëìíê ìí WRITE_ONCE() ë
+     ììíìì:
+
+	if (a)
+		WRITE_ONCE(b, a);
+	else
+		WRITE_ONCE(b, 42);
+
+     ìíìëë ëëë ëìíë ì ììëë.  ìëììëë ëìë ììíì
+     ììë, ìì ëì ëììì ììì ìëê íììì ëìëë ì ììëë.
+     ëìë ëëë ëê ìíì READ_ONCE() ë ììíìì.
+
+ (*) ìëë ëëë ììì ììí, íëì ëëë ìì ììíëììë ììì
+     êëí íêì ëìíë íëì í ìììê ìëêì ìì ìììëë
+     ëìëë "ëë íìë(load tearing)" ê "ìíì íìë(store tearing)"ì
+     ëìíëë.  ìë ëì, ììì ìííìê 16-bit ìíì ììíëìì
+     ìêíê 7-bit immediate field ë êìê ìëë, ìíìëë ëìì 32-bit
+     ìíì ëëì ìí ëêì 16-bit store-immediate ëëì ììíë íêëë:
+
+	p = 0x00010002;
+
+     GCC ë ìíì í ììêëì ëëê ë ê êëì ìíì íê ìí ëêê
+     ëë ììíëìì ììíê ëë ìë ìëì ììíë ììë íì ëë
+     êìí ìììì.  ëëì ì ììíë ìê ìëë ìëììë
+     ìêììêìëë.  ììë, ìêì ëìí (êëê êìì) ëêë GCC ê
+     volatile ìíìì ëììììë ì ììíë ììíê íìëë.  êë ëêê
+     ìëëë, WRITE_ONCE() ì ììì ëìê êì ìíì íìëì ëìíëë:
+
+	WRITE_ONCE(p, 0x00010002);
+
+     Packed êììë ììíë ê ìì ëìì ììë  ëë / ìíì íìëì
+     ìëí ì ììëë:
+
+	struct __attribute__((__packed__)) foo {
+		short a;
+		int b;
+		short c;
+	};
+	struct foo foo1, foo2;
+	...
+
+	foo2.a = foo1.a;
+	foo2.b = foo1.b;
+	foo2.c = foo1.c;
+
+     READ_ONCE() ë WRITE_ONCE() ëíëë ìê volatile ëíë ìê ëëì,
+     ìíìëë ì ìêì ëìëì 32-bit ëëì 32-bit ìíìì ììë ëíí
+     ì ììëë.  ìë 'foo1.b' ì êì ëë íìëê 'foo2.b' ì ìíì
+     íìëì ëë êìëë.  READ_ONCE() ì WRITE_ONCE() ê ì ìììë
+     íìëì ëì ì ììëë:
+
+	foo2.a = foo1.a;
+	WRITE_ONCE(foo2.b, READ_ONCE(foo1.b));
+	foo2.c = foo1.c;
+
+êëìë, volatile ë ëíë ëìì ëíìë READ_ONCE() ì WRITE_ONCE() ê
+íìíì ììëë.  ìë ëì, 'jiffies' ë volatile ë ëíëì ìê ëëì,
+READ_ONCE(jiffies) ëê í íìê ììëë.  ì ììë READ_ONCE() ì
+WRITE_ONCE() ê ìì volatile ììíìë êíëì ììì ììê ìë volatile
+ë ëíëì ìëë ëëë íêë ëìë ìê ëëìëë.
+
+ì ìíìë ëëìëì CPU ìë ììì íêë ìí ëëì ìê ëëì, êêì
+ìëìê ììë ìë ììì ëë êìí ëììì.
+
+
+CPU ëëë ëëì
+-----------------
+
+ëëì ìëì ëìì ìëê êë CPU ëëë ëëìë êìê ììëë:
+
+	íì		íì			SMP ìêì
+	===============	=======================	===========================
+	ëì		mb()			smp_mb()
+	ìê		wmb()			smp_wmb()
+	ìê		rmb()			smp_rmb()
+	ëìí ììì	read_barrier_depends()	smp_read_barrier_depends()
+
+
+ëìí ììì ëëìë ììí ëë ëëë ëëìë ìíìë ëëìë
+íííëë.  ëìí ìììì ìêìì ìíìë ìì ììêë íííì ììëë.
+
+ëë: ëìí ìììì ìë êì, ìíìëë íë ëëë ìëë ììë ììí
+êìë (ì: `a[b]` ë a[b] ë ëë íê ìì b ì êì ëì ëëíë)
+ììëëëë, C ìììë ìíìëê b ì êì ìì (ì: 1 ê êì) íì
+b ììì a ë ëë íë ìë (ì: tmp = a[1]; if (b != 1) tmp = a[b]; ) ë
+ëëì ììì íëë ëì êì ê ììëë.  ëí ìíìëë a[b] ë ëëí
+ìíì b ë ëëì ëëí ìë ììì, a[b] ëë ìì ëìì b êì êì ìë
+ììëë.  ì ëìì ëí ìêì ììë ìì  ëëììì ìììëëë,
+READ_ONCE() ëíëëí ëê ììíëê ìì êëë.
+
+SMP ëëë ëëìëì ìëíëììë ìíìë ììíììë ìíìë ëëìë
+ëëëë, íëì CPU ììë ììë ìêìì ììíê, êìë ìììë ìì
+ìëë ììë ííì êìë êìíê ëëìëë.  íìë, ìëì "Virtual
+Machine Guests" ìëììì ìêíììì.
+
+[!] SMP ëëë ëëìë SMP ììíììì êìëëëëì ìêì ìì ììì í
+ë, _ëëì_ ììëìì íì êìíìì, ëë ëì ëì ììíë êìëë
+ìëíê íëë.
+
+íì ëëìëì SMP ììíììë UP ììíììë ëíìí ìëíëë êê
+ëëì SMP íêë íìíëë ììëìì ìëëë.  íìë, ëìí ëëë I/O
+ìëìë íí ìììì MMIO íêë íìí ëìë ììë ìë ììëë.  ì
+ëëìëì SMP ê ìë ììíììë ììë ì ìëë, ìíìëì CPU ì ëëë
+ìíëìì ìëìë ëë ëìì ëëë ìíëììì ëëììì ëìë ììêì
+ìíì ìê ëëìëë.
+
+
+ëêì êê ëëì íìëë ììëë:
+
+ (*) smp_store_mb(var, value)
+
+     ì íìë íì ëìì íì êì ëìíê ììí ëëë ëëìë ìëë.
+     UP ìíìììë ìíìë ëëìëë ëí êì ìëêë ëìíì ììëë.
+
+
+ (*) smp_mb__before_atomic();
+ (*) smp_mb__after_atomic();
+
+     ìêëì êì ëííì ìë (ëíê, ëê, ìê, êìì êì) ìíë
+     íìë, íí ëíëì ììíì ììë ëë ìí íìëìëë.  ì
+     íìëì ëëë ëëìë ëìììë ììíìë ììëë.
+
+     ìêëì êì ëííì ìë, ìíëí (set_bit ê clear_bit êì) ëí
+     ìììë ììë ì ììëë.
+
+     í ìë, êì íëë ëíí íê ê êìì ëíëì ììíë êììíë
+     ëì ìëë ëìì:
+
+	obj->dead = 1;
+	smp_mb__before_atomic();
+	atomic_dec(&obj->ref_count);
+
+     ì ìëë êìì ìëìíë death ëíê ëíëì ììí êì ëì
+     *ììì* ëì êì ëëíê íëë.
+
+     ë ëì ìëë ìíì Documentation/atomic_ops.txt ëìë ìêíìì.
+     ìëì ìêëì ììíì íì êêíëë "Atomic operations" ìëììì
+     ìêíìì.
+
+
+ (*) lockless_dereference();
+
+     ì íìë smp_read_barrier_depends() ëìí ììì ëëìë ììíë
+     íìí ìì ëí íìë ë ì ììëë.
+
+     ìê rcu_dereference() ìë êìì ëìííìì RCU ììì ëìëììë
+     êëëëë ìì ììíë ììíë, ìë ëë êìê ììíì êì ëìë
+     ìêëë êì ëìëë.  ìêë, lockless_dereference() ë ìë ëìí
+     êìì RCU ì íê ëë ëëìë ììëê ììëë.
+
+
+ (*) dma_wmb();
+ (*) dma_rmb();
+
+     ìêëì CPU ì DMA êëí ëëìììì ììì êëí êì ëëëì ìêì
+     ìê ëìì ëí ììë ëìíê ìí ìêì ìë ëëëìì ììíê ìí
+     êëìëë.
+
+     ìë ëì, ëëììì ëëëë êìíê ëìíëíê ëëììì ìí
+     ìëì CPU ì ìí ìëì ìëê ìí ìí êì êìê, ì ëìíëíê
+     ìì êëíìì ë ìëë ììì(doorbell) ì ììíë ëëìì ëëìëë
+     ìêí ëìë:
+
+	if (desc->status != DEVICE_OWN) {
+		/* ëìíëíë ììíê ìì ëìíë ìì ìì */
+		dma_rmb();
+
+		/* ëìíë ìê ì */
+		read_data = desc->data;
+		desc->data = write_data;
+
+		/* ìí ìëìí ì ìììíì ëì */
+		dma_wmb();
+
+		/* ììêì ìì */
+		desc->status = DEVICE_OWN;
+
+		/* ëëììì ìëê ì MMIO ë ëëëì ëêíë êì */
+		wmb();
+
+		/* ëëììì ì ëìíëíë ìë */
+		writel(DESC_NOTIFY, doorbell);
+	}
+
+     dma_rmb() ë ëëììë ëìíëíëëí ëìíë ìììê ìì ììêì
+     ëëììì ëìíê íê, dma_wmb() ë ëëììê ììì ììêì êììì
+     ëê ìì ëìíëíì ëìíê ìììì ëëí íëë íëë.  wmb() ë
+     ìì ìêìì ìë (cache incoherent) MMIO ììì ìêë ìëíê ìì
+     ìì ìêìì ìë ëëë (cache coherent memory) ìêê ìëëììì
+     ëìíìê ìí íìíëë.
+
+     ìêì ìë ëëëì ëí ë ìëê íìíë Documentation/DMA-API.txt
+     ëìë ìêíìì.
+
+MMIO ìê ëëì
+----------------
+
+ëëì ìëì ëí memory-mapped I/O ìêë ìí íëí ëëìë êìê
+ììëë:
+
+	mmiowb();
+
+ìêì íì ìê ëëìì ëììë ììê ììí I/O ìììì ìêê ëëììë
+ììë ëìëë íìëë.  ì íìì íêë CPU->íëìì ìííììë ëìì
+ìì íëììì ëë ììêìë ìíì ëìëë.
+
+ë ëì ìëë ìíì "ë vs I/O ììì" ìëììì ìêíìì.
+
+
+=========================
+ìëì ìë ëëë ëëì
+=========================
+
+ëëì ìëì ìë ëë íìëì ëëë ëëìë ëìíê ìëë, ëê ììì
+êë íìëì ëëëìëë.
+
+ìêì _ììíì_ ëìì ìëíëë; íì ìííìììë ì ìëëë ë ëì
+ëìì ìêí ìë ììëëë êë ëììíì ìííì íì ìëììë
+êíëëë.
+
+
+ACQUIRING íì
+--------------
+
+ëëì ìëì ëìí ë êììë êìê ììëë:
+
+ (*) ìí ë
+ (*) R/W ìí ë
+ (*) ëíì
+ (*) ìëíì
+ (*) R/W ìëíì
+
+ê êììëë ëë êìì "ACQUIRE" ìíëììê "RELEASE" ìíëììì ëìì
+ììíëë.  ì ìíëììëì ëë ììí ëëìë ëííê ììëë:
+
+ (1) ACQUIRE ìíëììì ìí:
+
+     ACQUIRE í ììëë ëëë ìíëììëì ACQUIRE ìíëììì ìëë
+     ìí ìëëëë.
+
+     ACQUIRE ìì ììë ëëë ìíëììëì ACQUIRE ìíëììì ìëë íì
+     ìëë ìë ììëë.  smp_mb__before_spinlock() ìí ACQUIRE ê ìííë
+     ìëë ìì ìíìëì ìíì ëëì ìíìëì ëí ìì ëìëë.  ìê
+     smp_mb() ëë ìí ìììì êìíìì!  smp_mb__before_spinlock() ì ëì
+     ìííìììë ìì ìëêë ìëëë.
+
+ (2) RELEASE ìíëììì ìí:
+
+     RELEASE ìì ììë ëëë ìíëììëì RELEASE ìíëììì ìëëê
+     ìì ìëëëë.
+
+     RELEASE íì ììë ëëë ìíëììì RELEASE ìíëìì ìë ìì
+     ìëë ìë ììëë.
+
+ (3) ACQUIRE vs ACQUIRE ìí:
+
+     ëë ACQUIRE ìíëìì ììì ììë ëë ACQUIRE ìíëììì ìì
+     ACQUIRE ìíëìì ììì ìëëëë.
+
+ (4) ACQUIRE vs RELEASE implication:
+
+     RELEASE ìíëììëë ëì ììë ACQUIRE ìíëììì íë RELEASE
+     ìíëììëë ëì ìëëëë.
+
+ (5) ìíí ìêì ACQUIRE ìí:
+
+     ACQUIRE ìíëììì ìë ë ëìì ëì êëë ìëë ìííêë ëì
+     íë êëíìëë êëëë ëì ìêëì ëêë íì ìíí ì ììëë.
+     ìíí ëì ìë ëëìë ëííì ììëë.
+
+[!] ìê: ë ACQUIRE ì RELEASE ê ëëí ëëìììë ìí êê ì íëë
+íëíì ìì ëêì ììíëìì ìíì íëíì ìì ëëëë ëìì ì
+ìëë ìëìëë.
+
+RELEASE ìíì ììëë ACQUIRE ë ìì ëëë ëëìë ìêìë ìëëë,
+ACQUIRE ììì ìììê ACQUIRE ìíì ìíë ì ìê, RELEASE ìíì ìììê
+RELEASE ììì ìíë ìë ììë, ê ëêì ìììê ìëë ìëì ìë ìê
+ëëìëë:
+
+	*A = a;
+	ACQUIRE M
+	RELEASE M
+	*B = b;
+
+ë ëìê êì ë ìë ììëë:
+
+	ACQUIRE M, STORE *B, STORE *A, RELEASE M
+
+ACQUIRE ì RELEASE ê ë íëê íìëë, êëê ëì ACQUIRE ì RELEASE ê
+êì ë ëìì ëí êìëë, íë ëì ìê ìì ìì ëë CPU ì êììë
+ëêì ìëìê ììëë êì ë ì ììëë.  ìê ëí, ACQUIRE ì RELEASE
+ëê ìíëììì ììì ìíì ìì ëëë ëëìë ìêëìì -ìëëë-.
+
+ëìíê, ìì ëë ìììì RELEASE ì ACQUIRE ëê ìíëììì ììì ìí
+ìì ìì ëëë ëëìë ëííì ììëë.  ëëì, íëíì ììëì CPU
+ìíì RELEASE ì ACQUIRE ë êëìë ì ììëë, ëìê êì ìëë:
+
+	*A = a;
+	RELEASE M
+	ACQUIRE N
+	*B = b;
+
+ëìê êì ìíë ì ììëë:
+
+	ACQUIRE N, STORE *B, STORE *A, RELEASE M
+
+ìë ìëìë ëëëì ììí ìë ìì êìë ëì ìë ììëë.  íìë,
+êë ëëëì ììì ìëë RELEASE ë ëìí ìëë êìëë ëëëì ììí
+ì ììëë.
+
+	ìëê ìê ëìíì?
+
+	ìëê ììê íê ìëê ìëìë íë CPU ì ëí ììêìì,
+	ìíìëì ëí êì ìëë ìì íììëë.  ìíìë (ëë, êëì)
+	ê ìíëììëì ìëìíë, ëëëì ììë -ìë ìì-ëë.
+
+	íìë CPU ê ìíëììëì ìëì íëê ìêí ëìì.  ììëë
+	ìëìì ìëì ëì ììë êìë ìêí ëìë.  CPU ë ëìí ëì
+	ë ìíëììì ëì ìííë íê ëëë.  ëì ëëëì ììíëë,
+	ì ë ìíëììì ëìí ìííë êìíì ëì ìëíëë (ëë,
+	íì íìêìë, ìëëë).  CPU ë ììêë (ììëë ìëììë ëì
+	ììë) ìë ìíëììì ìííëë, ì ìë ìíëììì ììì
+	ëëëì íêíê, ë ìíëììë ëìì ìêíê ëëë.
+
+	íìë ëì ëì ìì ìë íìììëëì?  êë êìì ìëë
+	ìììëë ëìêë í êê, ìêì êêì ëëë ëëìë ëëê
+	ëëë, ì ëëë ëëìë ìì ìë ìíëììì ìëëëë ëëê,
+	ëëëì ìëìë íêëëë.  ìì ìë ìë êììíë ìì ì
+	ìêìëëë, ë êë ëêëì êë êììíì ìë êììë ìëë
+	íêí ì ìëë íì íëë.
+
+ëê ìëíìë ìë íëììë ìíìë ììíììì ììì ëí ëìì íì
+ìê ëëì, êë ìíìì ìíëí ëíìí ìíëììê íêê ìëëë ìë
+ììë - íí I/O ìììì êëíìë - ìëë ììë ì ìì êëë.
+
+"CPU ê ëí ëëì íê" ììë ìêíìê ëëëë.
+
+
+ìë ëì, ëìê êì ìëë ìêí ëìë:
+
+	*A = a;
+	*B = b;
+	ACQUIRE
+	*C = c;
+	*D = d;
+	RELEASE
+	*E = e;
+	*F = f;
+
+ëìì ìëí ìíìê ìê ì ììëë:
+
+	ACQUIRE, {*F,*A}, *E, {*C,*D}, *B, RELEASE
+
+	[+] {*F,*A} ë ìíë ìììë ìëíëë.
+
+íìë ëìê êì ê ëêëíì:
+
+	{*F,*A}, *B,	ACQUIRE, *C, *D,	RELEASE, *E
+	*A, *B, *C,	ACQUIRE, *D,		RELEASE, *E, *F
+	*A, *B,		ACQUIRE, *C,		RELEASE, *D, *E, *F
+	*B,		ACQUIRE, *C, *D,	RELEASE, {*F,*A}, *E
+
+
+
+ìíëí ëíìí íì
+----------------------
+
+ìíëíë ëíìí íë íì (ACQUIRE ì ëì) ì ìíëíë íìí íë íì
+(RELEASE ì ëì) ë ìíìë ëëìì ëìíêë ëìíëë.  ëëì, êë
+ìíììë ëëëë I/O ëëìê íìíë, êë ëëìëì ëë ëëìë
+ìêëììë íëë.
+
+
+ìëê ììíì íì
+--------------------
+
+êëë ëìíì íìë ìëíì ìí íëììë ìì ëíëë êê êìë êì
+ë ìêì ëìíêì ìíìììë ë ì ììëë: íë ìëíë êëëë
+íìíì íìí ìíì ê ìëíë ìëê ìí ììëë íëë ëìí.
+ìêëì ìì ììëë ììëì ëëí íê ìí, íëììë ìì ëê íë
+êëê êìë êëì ëêì ëëìë ëííëë.
+
+ëì, ìì ììë ìì ìëììë ëìê êì ìëí ìíìë ëëëë:
+
+	for (;;) {
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		if (event_indicated)
+			break;
+		schedule();
+	}
+
+set_current_state() ì ìí, íìí ìíê ëë í ëì ëëë ëëìê
+ìëìë ììëëë:
+
+	CPU 1
+	===============================
+	set_current_state();
+	  smp_store_mb();
+	    STORE current->state
+	    <ëì ëëì>
+	LOAD event_indicated
+
+set_current_state() ë ëìì êëë êìì ìë ììëë:
+
+	prepare_to_wait();
+	prepare_to_wait_exclusive();
+
+ìêë ìì ìíë ììí ìí ëì ëëë ëëìê ììì ìëíëë.
+ìì ìì ìíìë ëìê êì íìëë íëì ìí êëíë, ìêëì ëë
+ìëë ììì ëëë ëëìë ììíëë:
+
+	wait_event();
+	wait_event_interruptible();
+	wait_event_interruptible_exclusive();
+	wait_event_interruptible_timeout();
+	wait_event_killable();
+	wait_event_timeout();
+	wait_on_bit();
+	wait_on_bit_lock();
+
+
+ëëìë, êìêë ìííë ìëë ìëììë ëìê êì êëë:
+
+	event_indicated = 1;
+	wake_up(&event_wait_queue);
+
+ëë:
+
+	event_indicated = 1;
+	wake_up_process(event_daemon);
+
+wake_up() ëì ìí ìê ëëë ëëìê ëíëëë.  ëì êêëì ëêë
+êìëëì.  ëëìë íìí ìíê ììëê ìì ìíëê, ëëì ìëíë
+ìëê ìí STORE ì íìí ìíë TASK_RUNNING ìë ììíë STORE ììì
+ììíê ëëë.
+
+	CPU 1				CPU 2
+	===============================	===============================
+	set_current_state();		STORE event_indicated
+	  smp_store_mb();		wake_up();
+	    STORE current->state	  <ìê ëëì>
+	    <ëì ëëì>		  STORE current->state
+	LOAD event_indicated
+
+íëë ëíëëë, ì ìê ëëë ëëìë ëì êêëì ìëë ëêë
+êìëë, êëìë ììíëë.  ìê ìëíê ìí, X ì Y ë ëë 0 ìë
+ìêí ëì ìëë êì íì ìëì ìëí ìíìë ìêí ëìë:
+
+	CPU 1				CPU 2
+	===============================	===============================
+	X = 1;				STORE event_indicated
+	smp_mb();			wake_up();
+	Y = 1;				wait_event(wq, Y == 1);
+	wake_up();			  load from Y sees 1, no memory barrier
+					load from X might see 0
+
+ëë, ëì êìêê ííìëë, CPU 2 ì X ëëë 1 ì ëëê ëìë ì ìì
+êëë.
+
+ìì êëí êìêë íìëë ëìê êì êëì ììëë:
+
+	complete();
+	wake_up();
+	wake_up_all();
+	wake_up_bit();
+	wake_up_interruptible();
+	wake_up_interruptible_all();
+	wake_up_interruptible_nr();
+	wake_up_interruptible_poll();
+	wake_up_interruptible_sync();
+	wake_up_interruptible_sync_poll();
+	wake_up_locked();
+	wake_up_locked_poll();
+	wake_up_nr();
+	wake_up_poll();
+	wake_up_process();
+
+
+[!] ìììë ìëì êìë ìëì ëíëë ëëë ëëìëì êìê ììì ìë
+ìíìëì ìììë ìëê set_current_state() ë íìí ìíì ììë êì
+ëí ëëë ììë ëìì _ìëëë_ ìì êìíìì.  ìë ëì, ìììë
+ìëê ëìê êëë:
+
+	set_current_state(TASK_INTERRUPTIBLE);
+	if (event_indicated)
+		break;
+	__set_current_state(TASK_RUNNING);
+	do_something(my_data);
+
+êëê êìë ìëë ëìê êëë:
+
+	my_data = value;
+	event_indicated = 1;
+	wake_up(&event_wait_queue);
+
+event_indecated ìì ëêì ììë ìëìê my_data ìíì ëì êìëê ëìí
+ì ììëë.  ìë êììë ìì ìë ëë êêì ëìí ììì ììì ëëë
+ëëìë ìì ìì íëë.  ëëì ìì ììë ìëë ëìê êì:
+
+	set_current_state(TASK_INTERRUPTIBLE);
+	if (event_indicated) {
+		smp_rmb();
+		do_something(my_data);
+	}
+
+êëê êìë ìëë ëìê êì ëìì íëë:
+
+	my_data = value;
+	smp_wmb();
+	event_indicated = 1;
+	wake_up(&event_wait_queue);
+
+
+êìì íìë
+-------------
+
+êìì ëëìë ëííë íìëì ëìê êìëë:
+
+ (*) schedule() ê ê ììí êëì ìì ëëë ëëìë ëííëë.
+
+
+==============================
+CPU ê ACQUIRING ëëìì íê
+==============================
+
+SMP ììíììì ë ëêëì ëì êëí ííì ëëìë ìêíëë: íì ëì
+êìë ìì êëíìë ëë CPU ëì ëëë ììì ììì ìíì ëìëë.
+
+
+ACQUIRE VS ëëë ììì
+------------------------
+
+ëìì ìë ìêí ëìë: ììíì ëêì ìíë (M) ê (Q), êëê ìêì CPU
+ë êìê ììëë; ìêì ëìì ìëí ìíìê ëìíëë:
+
+	CPU 1				CPU 2
+	===============================	===============================
+	WRITE_ONCE(*A, a);		WRITE_ONCE(*E, e);
+	ACQUIRE M			ACQUIRE Q
+	WRITE_ONCE(*B, b);		WRITE_ONCE(*F, f);
+	WRITE_ONCE(*C, c);		WRITE_ONCE(*G, g);
+	RELEASE M			RELEASE Q
+	WRITE_ONCE(*D, d);		WRITE_ONCE(*H, h);
+
+*A ëì ìììëí *H ëì ìììêìê ìë ììë CPU 3 ìê ëìììì
+ëíìë ê CPU ììì ê ë ììì ìí ëíëì ìë ììì ììíêë ìë
+ëìë ììíì ììëë.  ìë ëì, ëìê êì ììëì ìíì êëíëë:
+
+	*E, ACQUIRE M, ACQUIRE Q, *G, *C, *F, *A, *B, RELEASE Q, *D, *H, RELEASE M
+
+íìë ëìê êì êìë ìì ì ììëë:
+
+	*B, *C or *D preceding ACQUIRE M
+	*A, *B or *C following RELEASE M
+	*F, *G or *H preceding ACQUIRE Q
+	*E, *F or *G following RELEASE Q
+
+
+
+ACQUIRE VS I/O ììì
+----------------------
+
+íìí (íí NUMA ê êëë) íê íìì, ëêì ìë ëë CPU ì ë ìíëìë
+ëëìì íëíì ìììì ììëë I/O ìììë, PCI ëëìë ìì ìêì
+íëíìê íì ëìì í ìëê ììëë, íìí ìê ëëë ëëìë ììí
+ìê ììì, PCI ëëìë ìí ìëì ëë êìë ëì ì ììëë.
+
+ìë ëìì:
+
+	CPU 1				CPU 2
+	===============================	===============================
+	spin_lock(Q)
+	writel(0, ADDR)
+	writel(1, DATA);
+	spin_unlock(Q);
+					spin_lock(Q);
+					writel(4, ADDR);
+					writel(5, DATA);
+					spin_unlock(Q);
+
+ë PCI ëëìì ìí ëìê êì ëì ì ììëë:
+
+	STORE *ADDR = 0, STORE *ADDR = 4, STORE *DATA = 1, STORE *DATA = 5
+
+êëê ìëê ëë íëììì ìëìì ììí ì ììëë.
+
+
+ìë êìì mmiowb() ë ìíëì ëê ìì ììíì íëë, ìë ëë ëìê
+êìëë:
+
+	CPU 1				CPU 2
+	===============================	===============================
+	spin_lock(Q)
+	writel(0, ADDR)
+	writel(1, DATA);
+	mmiowb();
+	spin_unlock(Q);
+					spin_lock(Q);
+					writel(4, ADDR);
+					writel(5, DATA);
+					mmiowb();
+					spin_unlock(Q);
+
+ì ìëë CPU 1 ìì ììë ëêì ìíìê PCI ëëìì CPU 2 ìì ììë
+ìíìëëë ëì ëììì ëìíëë.
+
+
+ëí, êì êêìì ìíìë ìì ëëê ìíëë ëëë ëëê ìíëê ìì
+ìíìê ìëëêë êìíëë mmiowb() ì íìê ìììëë:
+
+	CPU 1				CPU 2
+	===============================	===============================
+	spin_lock(Q)
+	writel(0, ADDR)
+	a = readl(DATA);
+	spin_unlock(Q);
+					spin_lock(Q);
+					writel(4, ADDR);
+					b = readl(DATA);
+					spin_unlock(Q);
+
+
+ë ëì ìëë ìíì Documenataion/DocBook/deviceiobook.tmpl ì ìêíìì.
+
+
+=========================
+ëëë ëëìê íìí ê
+=========================
+
+íëí ììí ìì ììë, ìë SMP ìëì ìì ììëë ìê ìëëë ëìíë
+ììì ìë ìêëì ìëëê ëìíë êìë ëì êìê ëëì ëëë
+ìíëìì ìëìë ìëììë ëìê ëì ììëë.  íìë, ìëìê ëìê
+_ë ì ìë_ ëêì íêì ììëë:
+
+ (*) íëììê ìí ìì.
+
+ (*) ìíë ìíëìì.
+
+ (*) ëëìì ìê.
+
+ (*) ìíëí.
+
+
+íëììê ìí ìì
+--------------------
+
+ëê ììì íëììë êì ììíì ìëë, ììíì ëê ììì CPU ë ëìì
+êì ëìíì ëí ììì í ì ììëë.  ìë ëêí ëìë ììí ì ìê,
+ì ëìë íêíë ìëì ëëì ëì ììíë êìëë.  íìë, ëì ìëí
+ëìì ëìê, ëëì ëì êëíêë íëë ëì ììíì ìê ìì ìëíë
+êì ëìëë.  êë êì, ë CPU ëëì ìíì ëìë ìíëììëì ìëìì
+ëê ìí ììíê ììê ëììì íëë.
+
+ìë ëì, R/W ìëíìì ëë ìíêëë ìêí ëìë.  êëëë íëììë
+ìëíìì ëê íëììë ëìíì ììë ëíëì ìëìë ìëíìì ììì
+ì ììëë:
+
+	struct rw_semaphore {
+		...
+		spinlock_t lock;
+		struct list_head waiters;
+	};
+
+	struct rwsem_waiter {
+		struct list_head list;
+		struct task_struct *task;
+	};
+
+íì ëê ìí íëììë êìê ìí, up_read() ë up_write() íìë ëìê
+êì ìì íì íëë:
+
+ (1) ëì ëê ìí íëìì ëìëë ìëìëì ìê ìí ì ëê ìí
+     íëìì ëìëì next íìíë ììëë;
+
+ (2) ëê ìí íëììì task êììëì íìíë ììëë;
+
+ (3) íë ëê ìí íëììê ìëíìë íëíìì ìëê ìí task
+     íìíë ìêí íëë;
+
+ (4) íë íìíì ëí wake_up_process() ë íìíëë; êëê
+
+ (5) íë ëê ìí íëììì task êììë ìê ìë ëíëìë íìíëë.
+
+ëë ëíìë, ëì ìëí ìíìë ìííì íëë:
+
+	LOAD waiter->list.next;
+	LOAD waiter->task;
+	STORE waiter->task;
+	CALL wakeup
+	RELEASE task
+
+êëê ëì ì ìëíëì ëë ììë ìíëëë, ìëìì ììë ì ììëë.
+
+íë ìëíìì ëêìì ëìêê ìëíì ëì ëìëë, íë ëê íëììë
+ëì ëìë ìì ììëë; ëì ììì task íìíê ìêí ëê êëëëë.
+ëìëë ëê íëììì ìíì ìê ëëì, ììì task íìíê ëìíì next
+íìíê ìíìê _ìì_ ìíìëë, ëë CPU ë íë ëê íëììë ììí
+ëëê up*() íìê next íìíë ìê ìì ëê íëììì ìíì ëê êëë
+ì ììëë.
+
+êëê ëë ìì ìëí ìíìì ìë ìì ììëëì ìêí ëì:
+
+	CPU 1				CPU 2
+	===============================	===============================
+					down_xxx()
+					Queue waiter
+					Sleep
+	up_yyy()
+	LOAD waiter->task;
+	STORE waiter->task;
+					Woken up by other event
+	<preempt>
+					Resume processing
+					down_xxx() returns
+					call foo()
+					foo() clobbers *waiter
+	</preempt>
+	LOAD waiter->list.next;
+	--- OOPS ---
+
+ì ëìë ìëíì ëì ìììë íêë ìë ìêìë, êëê ëë down_xxx()
+íìê ëíìíê êìë ìí ìíëì ëëì ìììë íëë.
+
+ìê íêíë ëëì ëì SMP ëëë ëëìë ìêíë êëë:
+
+	LOAD waiter->list.next;
+	LOAD waiter->task;
+	smp_mb();
+	STORE waiter->task;
+	CALL wakeup
+	RELEASE task
+
+ì êìì, ëëìë ëë ëëì ììì ëëë ìììê ììíì ëëì CPU
+ëìê ëëì ëì ëëë ìììëë ììì ììë êìë ëìê ëëëë.
+ëëì ììì ëëë ìììëì ëëì ëë ììê ìëëë ììêì
+ìëëëêë ëìíì _ììëë_.
+
+ëì íëìì ììí - ìê ëìê ëì ìì - ìì smp_mb() ë êì ìíìëê
+ììëë CPU ìììì ììë ëêêë íì ìê ììì ììëë ëëì ëëëë
+íë ìíìë ëëìì ëìëë.  ìì íëì CPU ë ììëë, CPU ì ììì
+ìì ëìì ê ìì ëëêëì ììì ìëí êëë.
+
+
+ìíë ìíëìì
+-----------------
+
+ìíë ìíëììì êìììëë íëììê ìíìììë ëëëë ê ì ìëë
+ìì ëëë ëëìë ëííê ë ìëë ëííì ììë, ìëì ìëí ììíë
+êë ì íëìëë.
+
+ëëëì ìë ìíë ììíê íë ìíì ëí (ììì ëë ììì) ìëë
+ëííë ìíë ìíëììì ëë SMP-ìêì ëì ëëë ëëì(smp_mb())ë
+ìì ìíëììì ìê ëì ëííëë.  ìë ìíëììì ëìì êëì
+íííëë:
+
+	xchg();
+	atomic_xchg();			atomic_long_xchg();
+	atomic_inc_return();		atomic_long_inc_return();
+	atomic_dec_return();		atomic_long_dec_return();
+	atomic_add_return();		atomic_long_add_return();
+	atomic_sub_return();		atomic_long_sub_return();
+	atomic_inc_and_test();		atomic_long_inc_and_test();
+	atomic_dec_and_test();		atomic_long_dec_and_test();
+	atomic_sub_and_test();		atomic_long_sub_and_test();
+	atomic_add_negative();		atomic_long_add_negative();
+	test_and_set_bit();
+	test_and_clear_bit();
+	test_and_change_bit();
+
+	/* ìêíì ë */
+	cmpxchg();
+	atomic_cmpxchg();		atomic_long_cmpxchg();
+	atomic_add_unless();		atomic_long_add_unless();
+
+ìêëì ëëë ëëì íêê íìí ACQUIRE ëëì RELEASE ëë ìíëììëì
+êíí ëì êì ìë ìì ëíëì ììíë ììí ë ëì ììëëë.
+
+
+ëìì ìíëììëì ëëë ëëìë ëííì _ìê_ ëëì ëìê ë ì
+ììë, RELEASE ëëì ìíëììëê êì êëì êíí ë ììë ìë
+ììëë:
+
+	atomic_set();
+	set_bit();
+	clear_bit();
+	change_bit();
+
+ìêëì íìíëë ììí (ìë ëë smp_mb__before_atomic() êì) ëëë
+ëëìê ëìììë íê ììëìì íëë.
+
+
+ìëì êëë ëëë ëëìë ëííì _ìê_ ëëì, ìë íêììë (ìë
+ëë smp_mb__before_atomic() ê êì) ëììì ëëë ëëì ììì íìíëë.
+
+	atomic_add();
+	atomic_sub();
+	atomic_inc();
+	atomic_dec();
+
+íê ëìí ììì ìí ììëëë, íê ëìí ììì êí êêê ììíêë
+íì ìëëë ëëë ëëìë íìì ìì êëë.
+
+êìì ìëì êëíê ìí ëíëì ììí ëììë ììëëë, ëíëì
+ììíë ëìë ëíëë ììììë ììëêë íìíë ìì ìë ìëí
+ëíëìë ìê ìì êìê ëëì ëëë ëëìë ìë íì ìì êëë.
+
+ëì ìë ëì êìíê ìí ììëëë, ë êë ëìì ìëììë ììì íì
+ììëë ìííì íëë ëëë ëëìê íìí ì ììëë.
+
+êëììë, ê ìììììë ëëë ëëìê íìíì ìëì ìëí êëíì
+íëë.
+
+ìëì ìíëììëì íëí ë êë ëìëìëë:
+
+	test_and_set_bit_lock();
+	clear_bit_unlock();
+	__clear_bit_unlock();
+
+ìêëì ACQUIRE ëì RELEASE ëì ìíëììëì êííëë.  ë êë ëêë
+êíí ëìë ìêëì ì ë ìííë íì ëìë, ìêëì êíì ëì
+ìííììì ììí ë ì ìê ëëìëë.
+
+[!] ìë ìíì ììí ì ìë íìí ëëë ëëì ëêëì ìëë, ìë CPU
+ìì ìíë ììíëìì ììì ìì ëëë ëëìë ëííê ìì ìíë
+ìíëììê ëëë ëëìë íê ììíë êì ëíìí êìê ìì ì ìê
+ëëì, íë íì ëëë ëëì ëêëì ìë êì no-op ìë ìëëëë.
+
+ë ëì ìëë ìíì Documentation/atomic_ops.txt ë ìêíìì.
+
+
+ëëìì ììì
+---------------
+
+ëì ëëììê ëëëì ëí ë ì ìëë, êëê ëë êêëì CPU ìë ëì
+ëëë ììì ìíìë ëìê ëëë.  êë ëëììë ììíê ìíì,
+ëëìëë ëí ìíí ìëë ììë ìëë ëëë ìììë ëëìì íëë.
+
+íìë, ìëí CPU ë ìëí ìíìëëì ëì íë CPU ë ìíìëê
+ìììëì ìëì íê, ìííêë ëííëê ë íìììë ìêíê ëë
+ëëìë ìëì ìììëê ìì ëìì ìììëì ëëìììë ììë ììëë
+ëìíì ëí ì ìë - ëëììê ìëìì íê í - ììì ëì ë
+ëëìëëë.
+
+ëëì ìëì ëëìì, I/O ë ëëì ìëê êë ìììëì ììí ììììê
+ëë ì ìëì ìê ìë, - inb() ë writel() ê êì - ììí ììì ëíì
+íí ìëììì íëë.  ìêëì ëëëì ëëìì ëíìí ëëë ëëìì
+ëìì ììì íê ëëì, ìêëì ììì í êì ëìì ëê íê ìëìëë:
+
+ (1) ìë ììíìì I/O ìíìë ëë CPU ì ìêëê ìì ëììì ìëë,
+     ëëì _ëë_ ëì ëëìëìë ëì ììëììë íê mmiowb() ë
+     íëíì ììì ëìëìê ìì ê íìëìì íëë.
+
+ (2) ëì ììì íìëì ìíë ëëë ììì ììì êë I/O ëëë ìëìë
+     ìêíëë, ììë ëìê ìíì _íì_ ëëë ëëìëì íìíëë.
+
+ë ëì ìëë ìíì Documentation/DocBook/deviceiobook.tmpl ì ìêíììì.
+
+
+ìíëí
+--------
+
+ëëìëë ììì ìíëí ìëì ëíì ìí ìíëí ëí ì ìê ëëì
+ëëìëì ì ë ëëì êìì ëëìì ìì ëë ììì ëëì ìí êìí ì
+ììëë.
+
+ëëìëì íëíìí ìíëììëì ëë ìíëí ëíìíë ììì ììëêë
+íë ììë ëì ìíëíì ëíìí (ëì í íí) ë íí ìë ìí êìì -
+ììí ëëììëëë - ììì íëë.  ëëìëì ìíëí ëíì ìí ìì
+ëì, íë ëëìëì ììë ëë CPU ìì ìíìì ìë ìê, ìíëíë
+íìì ìíëíê ìëëë ììë ëëì ììëì ëíëë ëì ììì ìíëí
+íëëë êì ëíìë ëì ìì ììë ëëë.
+
+íìë, ìëëì ëììíì ëìí ëììíë êë ìëë ìëë ëëë
+ëëìëë ìêí ëìë.  ëì ì ëëìëì ììê ìíëíê ëíìíë
+ìíì ìëì ììê ììê ëëìëì ìíëí íëëê íìëìëë:
+
+	LOCAL IRQ DISABLE
+	writew(ADDR, 3);
+	writew(DATA, y);
+	LOCAL IRQ ENABLE
+	<interrupt>
+	writew(ADDR, 4);
+	q = readw(DATA);
+	</interrupt>
+
+ëì ìì êìì ìëí ìíëì ìëë ëìí ëììíìì ìíìë ìëëì
+ëììíì ëëìë ííìë ìíì ìíì ììë ìë ììëë:
+
+	STORE *ADDR = 3, STORE *ADDR = 4, STORE *DATA = y, q = LOAD *DATA
+
+
+ëì ìì êìì ìíëììëë, ëìììë ëìììë ëëìê ììëì
+ììëë ìíëí ëíìí ìììì ììë ìììê ëêìë ììì
+ìíëíìì ììë ìììì ìì ìë ìëê - êëê ê ëëë - êìíìë
+íëë.
+
+êë ìì ììì ììëë I/O ìììëì ëìì I/O ëëìë íìíë ìêí
+ìì êìì I/O ëììíìì ëêíë ëë ìíëììì íííê ëëì
+ìëììëë ìëê ëìê ëì ììëë.  ëì ìêëë ìëì ìëë mmiowb()
+ê ëìììë ììë íìê ììëë.
+
+
+íëì ìíëí ëíê ëëì CPU ìì ìíììë ìë íì ìì ë ëí
+ìììë ëìí ìíì ììë ì ììëë.  ëì êë êìëë, ììë ëìíê
+ìí ìíëí ëíìí ëì ììëìììë íëë.
+
+
+======================
+ìë I/O ëëìì íê
+======================
+
+I/O ëëëì ìêí ë, ëëìëë ëëì ììí ììì íìë ììíì íëë:
+
+ (*) inX(), outX():
+
+     ìêëì ëëë êêëëë I/O êêì ììêë íëë ìëíê
+     ëëìììëëë, êê CPU ëë ëë ìììëë.  i386 ê x86_64
+     íëììëì ììë íëí I/O êê ììì ììíê ëëìë êìê
+     ììëëë, ëë ëì CPU ëìë êë ììì ììíì ììëë.
+
+     ëë êë ì, PCI ëìë I/O êê ììì ììíëë, ìë - i386 ê x86_64
+     êì CPU ìì - CPU ì I/O êê ìììë ìê ëìëëë.  íìë, ìë
+     ëí, ííë ëìí I/O êêì ìë CPU ììë CPU ì ëëë ëì êì I/O
+     êêìë ëìë ìë ììëë.
+
+     ì êêìëì ìììë (i386 ëììë) ììíê ëêí ëëëë, ìêì
+     (PCI íìí ëëìì êì) ëëìëì ìë ììí ëìíì ììì
+     ììëë.
+
+     êêëì ìíêì ììíê ììê ëìëëë.
+
+     êêëì ëë íìì ëëëì I/O ìíëììêì ììë ììíê
+     ëìëìë ììëë.
+
+ (*) readX(), writeX():
+
+     ìêëì ììëë CPU ìì ìë ììí ììê ëììê êíëì ìëìì
+     ëí ëì ìëë ìëì ììì íë ëëë ìëìì ììë íìì ìí
+     êìëëë.  ìë ëì, ììì i386 ìííì ëìììë MTRR ëììíë
+     ìë ììíëë.
+
+     ìëììëë, íëíì êëí ëëììë ììì íëê ìëëë, ìêëì
+     ììí ììê ëììê êíëì ìê ëìë êëë.
+
+     íìë, (PCI ëëìì êì) ìêì íëììë ëì êêì ìíëë ìíì
+     ìêìí ì ììëë; ìíì ëëì ììë ìí ìíë êì(flush), êì
+     ìììì ëëë íë êìë êëíëë[*], íìë PCI ì êìë êì
+     ëëììë íê êì ììììì ëëëìëë êëíëë.
+
+     [*] ìì! ììì êê êì ìììì ëëë ìëíë êì ìëìì ììí
+         ìë ììëë - ìë 16650 Rx/Tx ìëì ëììíë ìêí ëìì.
+
+     íëíì êëí I/O ëëëê ììëë, ìíì ëëëì ììë ìíëë
+     íê ìíì mmiowb() ëëìê íìí ì ììëë.
+
+     PCI íëìì ììì ìíììì ëí ë ëì ìëë ìíì PCI ëììë
+     ìêíìê ëëëë.
+
+ (*) readX_relaxed(), writeX_relaxed()
+
+     ìêëì readX() ì writeX() ë ëìíìë, ë ìí ëëë ìì ëìì
+     ìêíëë.  êìììë, ìêëì ìëì ëëë ììì (ì: DMA ëí) ìë
+     LOCK ìë UNLOCK ìíëììëìë ììë ëìíì ììëë.  ììê
+     íìíëë, mmiowb() ëëìê ììë ì ììëë.  êì ìë ìììì
+     ìíë ìììë êìì ëíìë ììê ìììì ìì ëìê ëëëë.
+
+ (*) ioreadX(), iowriteX()
+
+     ìêëì inX()/outX() ë readX()/writeX() ìë ììë íë ìììì íìì
+     ììíê ìíë êìëë.
+
+
+================================
+êìëë ììíì ìí ìì ëë
+================================
+
+ììììë CPU ë ììì íëêëì ëí íëêë ê ìììë ìêìì ìíë
+êìë ëìê íìë ìëììëë ììë êì ìììì ìëëê êìëììë
+íëë.  (i386 ìë x86_64 êì) ìë CPU ëì (powerpc ë frv ì êì) ëë
+êëì ëí ìì ìëìì ììì ìëëë, ìííì ììì ìë ìì ëëììë
+ììì ëí ììì êì ìíë êì (DEC Alpha) ë êìíìë íëë.
+
+ì ëì CPU ë ìììê ìììë ììíëì ìíëì ìíë ëì í
+ììíëìì ìì ììíëìì ììììëë ê ìì ììíëìì ê ëì ììì
+ììíëìì ìíëê ìì ìë[*]ë ì ììì íëë ìì ììë ììì ìíë
+ììëë - ëë ììì ëëììë - ìíí ì ììì ìëíëë; ì ììì
+ìêìì ìììì ìëíëë.
+
+ [*] ìë ììíëìëì íë ììì íê - ìê ìëë ëêëëì, ëììíë
+     ëëëë ëêëëì -  ë ëë, ëë ììíëìëì ìë ëë íêì
+     ììë ìë ììëë.
+
+CPU ë ììììëë ìë íêë ëëì ìë ììíëì ìíìë ììëë ìë
+ììëë.  ìë ëì, ëì ëêì ììëë ììíëìì ë ë êì ëììíì
+ìììì ê (immediate value) ì ììëëëë, ìëì ììíëìì ëëì ìë
+ììëë.
+
+
+ëìíê, ìíìëë ìì íëêëì ìêìë ìììëë ììíëì ìíëì
+ììì ëêì ìëëë ìêíëëë ìëì í ì ììëë.
+
+
+===============
+CPU ììì ìí
+===============
+
+ììë ëëë ìíëììëì ììí ììì ìëê ììëëìë CPU ì ëëë
+ììì ììíë ììì ììí ìíì ìêìì êëíë ëëë ìíëì ììíì
+ìí ìë ëë ìíì ëìëë.
+
+í CPU ê ììíì ëë ëëëê ììë íí ìíììíëë, ëëë ììíì
+CPU ì ììëê ëëë ëëìë êììë íëë, ëëë ëëìëì ëëëì CPU
+ì êêì ìì ìì ìííìììì ëìíëë (ëëë ëëìëì ëëììëë
+ëì êëì ìììì ëìíëë):
+
+	    <--- CPU --->         :       <----------- Memory ----------->
+	                          :
+	+--------+    +--------+  :   +--------+    +-----------+
+	|        |    |        |  :   |        |    |           |    +--------+
+	|  CPU   |    | Memory |  :   | CPU    |    |           |    |        |
+	|  Core  |--->| Access |----->| Cache  |<-->|           |    |        |
+	|        |    | Queue  |  :   |        |    |           |--->| Memory |
+	|        |    |        |  :   |        |    |           |    |        |
+	+--------+    +--------+  :   +--------+    |           |    |        |
+	                          :                 | Cache     |    +--------+
+	                          :                 | Coherency |
+	                          :                 | Mechanism |    +--------+
+	+--------+    +--------+  :   +--------+    |           |    |	      |
+	|        |    |        |  :   |        |    |           |    |        |
+	|  CPU   |    | Memory |  :   | CPU    |    |           |--->| Device |
+	|  Core  |--->| Access |----->| Cache  |<-->|           |    |        |
+	|        |    | Queue  |  :   |        |    |           |    |        |
+	|        |    |        |  :   |        |    |           |    +--------+
+	+--------+    +--------+  :   +--------+    +-----------+
+	                          :
+	                          :
+
+íì ëëë ìíìë íë ìíëììì ììí CPU ì ìì ëìì ëìì ìëí
+ìë ìê ëëì íë CPU ì ëêìë ëìì ìì ìë ììë, ëë CPU ê
+êìì êëëë ìì ìêì ëìëìì íë ììëìì ìêíë CPU ë ìëíê
+íë ììì ëí ìíëììì ìê ëëë ê ìíì ìíìíê ëëì íë
+ìíëììì ììí ëëëì ìììë ììë íêìë ëíë êìëë.
+
+CPU ììë íëêëì ìêìì ììëëêë ìêìëë ììíëìëì ìë
+ììëë ìëìíì ìíí ìë ììëë.  ìë ììíëìëì ëëë ìíì
+ìíëììì ëëëë ì ìíëììëì ìí ìíë ëëë ììì íì ëìêê
+ëëë.  ììë ì ìíëììëì íë íì ìë ììëë ìíëëë ëì ì
+ìê, ëë ììíëìì ìëë êëëëë êìëê ìêìë ìíì êìíëë.
+
+ëëë ëëìê íë ìì CPU ìììì ìììì ëëë ìììì ìììì ìì,
+êëê ìíëììì íêê ììíì ëë êììëìê ííì êìë ìíëë
+ììë ììíë êìëë.
+
+[!] CPU ëì íì êë ììì ëëì ìíìë íëêë ììëë ììë êìë
+ëê ëëì, ììì CPU ëììë ëëë ëëìë ììí íìê _ììëë_.
+
+[!] MMIO ë ëë ëëìì ìììëì ìì ììíì ìíí ìë ììëë.  ìë
+ëëììê ììì ëë ëëë ìëìì íìì ìí êìë ìë ìê, CPU ê
+êìê ìì ìë ìë íìí ëëìì íì ììíëìì ììì ìíì êìë
+ìë ììëë.
+
+
+ìì ìêì
+-----------
+
+íìë ìì ììì ììêí êìë ëìíì ììëë: ììëì ìêìì êìë
+êëëìë, ê ìêìì ìììë ììë êëë ëìì ììëë.  í CPU ìì
+ëëìì ëê ìíì ììììëë ììíì ëë CPU ìê ëììê ëìë, ëë
+CPU ëìêë êì ììë ëìê ë êëë ëìì ìëë ëìëë.
+
+
+ëêì CPU (1 & 2) ê ëë ìê, ê CPU ë ëêì ëìí ìì(CPU 1 ì A/B ë,
+CPU 2 ë C/D ë êìëë)ê ëëë ìêëì ìë ììíì ëëëê ìêí
+ëìë:
+
+	            :
+	            :                          +--------+
+	            :      +---------+         |        |
+	+--------+  : +--->| Cache A |<------->|        |
+	|        |  : |    +---------+         |        |
+	|  CPU 1 |<---+                        |        |
+	|        |  : |    +---------+         |        |
+	+--------+  : +--->| Cache B |<------->|        |
+	            :      +---------+         |        |
+	            :                          | Memory |
+	            :      +---------+         | System |
+	+--------+  : +--->| Cache C |<------->|        |
+	|        |  : |    +---------+         |        |
+	|  CPU 2 |<---+                        |        |
+	|        |  : |    +---------+         |        |
+	+--------+  : +--->| Cache D |<------->|        |
+	            :      +---------+         |        |
+	            :                          +--------+
+	            :
+
+ì ììíì ëìê êì íìì êëë ìêí ëìë:
+
+ (*) íìë ììëìì ìì A, ìì C ëë ëëëì ììí ì ìì;
+
+ (*) ììë ììëìì ìì B, ìì D ëë ëëëì ììí ì ìì;
+
+ (*) CPU ììê íêì ììì ìêíë ëì, ëë ììë - ëí ììëìì
+     ëëëì ëëêë ììì ëëë íêë íê ìí - ììíì ëë ëëì
+     ììì íê ìí ëìë ììí ìë ìì;
+
+ (*) ê ììë ììíì ëëì ëëëê ìêìì ëìê ìí íë ììì
+     ììëìì í ìíëììëì íë êì;
+
+ (*) íë ìêì íë ììì ìë ììíë ëììì íëí ëëì ìíìë,
+     ììì íì ìíëììëì ì ëëì êêì ìíì ëì ì ìë íìëë,
+     íëì ëì ìì.
+
+ìì, ìëì CPU ìì ëêì ìê ìíëììì ëëëë, íë CPU ì ììì
+ììë ììë ìíëììì ëëëì ëìíê ìí ë ìíëìì ììì ìê
+ëëìë ììíë ìíì ììí ëìë:
+
+	CPU 1		CPU 2		COMMENT
+	===============	===============	=======================================
+					u == 0, v == 1 and p == &u, q == &u
+	v = 2;
+	smp_wmb();			v ì ëêì p ì ëê ììì ëì êì
+					 ëëí í
+	<A:modify v=2>			v ë ìì ìì A ì ììíê ììí
+	p = &v;
+	<B:modify p=&v>			p ë ìì ìì B ì ììíê ììí
+
+ìê ëëë ëëìë ììíì ëë CPU ëì ìê ëëìë ììí CPU ì ììê
+ìëë ììë ìëìí ë êìë ììíê ëëëë.  íìë ìì ëëì CPU ê
+ê êëì ììë íë ìíì ìêí ëìë:
+
+	CPU 1		CPU 2		COMMENT
+	===============	===============	=======================================
+	...
+			q = p;
+			x = *q;
+
+ìì ëêì ìê ìíëììì ììë ììë ììëì ëí ì ìëë, ëëì CPU
+ì í ììì ëë ìì ìëíê ëìí v ë ëê ìë ììëìì íë ìììì
+ìëìíê ììëë ìì, p ë ëê ìë ììëìì ëëì CPU ì ëë ììì
+ìëìí ëìëëì ì ìê ëëìëë.
+
+	CPU 1		CPU 2		COMMENT
+	===============	===============	=======================================
+					u == 0, v == 1 and p == &u, q == &u
+	v = 2;
+	smp_wmb();
+	<A:modify v=2>	<C:busy>
+			<C:queue v=2>
+	p = &v;		q = p;
+			<D:request p>
+	<B:modify p=&v>	<D:commit p=&v>
+			<D:read p>
+			x = *q;
+			<C:read *q>	ììì ìëìí ëê ìì v ë ìì
+			<C:unbusy>
+			<C:commit v=2>
+
+êëììë, ëêì ììëì ëë CPU 2 ì ììììëë ìëìí ë êììë,
+ëëì êì ììë, ìëìíì ììê CPU 1 ìì ëëìì ììì ëìí
+êìëë ëìì ììëë.
+
+
+ìêì êìíê ìíì, ëìí ììì ëëìë ìê ëëìë ëë ìíëììë
+ììì ëìì íëë.  ìëê íìëì ììê ëì ëíìíë ìëíê ìì
+ìêì íë ìëíëë êìíê ëëë.
+
+	CPU 1		CPU 2		COMMENT
+	===============	===============	=======================================
+					u == 0, v == 1 and p == &u, q == &u
+	v = 2;
+	smp_wmb();
+	<A:modify v=2>	<C:busy>
+			<C:queue v=2>
+	p = &v;		q = p;
+			<D:request p>
+	<B:modify p=&v>	<D:commit p=&v>
+			<D:read p>
+			smp_read_barrier_depends()
+			<C:unbusy>
+			<C:commit v=2>
+			x = *q;
+			<C:read *q>	ììì ìëìí ë v ë ìì
+
+
+ìë ëëì ëìë DEC Alpha íëììëìì ëêë ì ìëë, ìëì ëìí
+ëìë ì ë ì ììí ìëì êìí ì ìë ëíë ììë êìê ìê
+ëëìëë.  ëëëì CPU ë í ìê ìíëììì ëëë ìììê ëë ìê
+ìíëììì ììììëë ëìí ììì ëëìë ëíìíëëë, ëëê êëê
+ìëê ëëì ìêì ììíì ìëëë.
+
+ëë CPU ëë ëíë ììë êìê ìì ì ììëëë íëí ëëë ìììë
+ìí ëìí ììë ììì ììì íìíëë.  Alpha ììë ìì ë ëëë
+ëëìì ëìë ê ììì íìì ììë ìêíìëë.
+
+
+ìì ìêì VS DMA
+------------------
+
+ëë ììíì DMA ë íë ëëììì ëíìêì ìì ìêìì ììíìë
+ììëë.  êë êì, CMA ë ìëíë ëëììë RAM ìëëí ìëë ëìíë
+ìì ìë ìëë, ëí ìì ëìì ìë CPU ì ììì ëëëê ìê ìì RAM ì
+ëë êì ììì ììì ì ìê ëëìëë.  ì ëìë íêíê ìíì, ìëì
+ììí ëëìì ê CPU ììì ëìëë ëíëì íëì ìììë íëë (êëê
+êêëì ëíí - invalidation - ë ìí ì ìêì).
+
+ëí, ëëììì ìí RAM ì DMA ë ììì êì ëëììê ìêë ìëí ìíì
+CPU ì ìììì RAM ìë ìììë ëí ìì ëìì ìí ëììì ìë ìê, CPU
+ì ììì ììíë ìì ëìì íë ììëìì CPU ì ìììì ììëê ëì
+êì ììëìê ìêìë RAM ì ìëìí ëìëë ìì ììë ìêëë ìë
+ììëë.  ì ëìë íêíê ìíì, ìëì ììí ëëìì ê CPU ì ììì
+ëìê ëë ëíëì ëíí ììì íëë.
+
+ìì êëì ëí ë ëì ìëë ìíì Documentation/cachetlb.txt ë
+ìêíìì.
+
+
+ìì ìêì VS MMIO
+-------------------
+
+Memory mapped I/O ë ìëììë CPU ì ëëë êê ëì í ìëìì ëëì ìë
+ëëë ììì ìëììëë, ì ìëìë ìëìì, RAM ìë ííë ìëììë
+ëë íìì êìëë.
+
+êë íì êìëìë ìëììë êë ìììë ììë ììí ìííê ëëìì
+ëìë êëë ííëë êìëë.  ì ëì MMIO ìììë ëì ìëìì ììë
+ëëë ìììë ììí ì ìëë ëìëë.  ìë êìì ëëë ëëìëìëë
+ìëì ìê, ëì ììë ëëë ìê ìíëììê MMIO ìììê ìë ëììëë
+ììììëë íë ììë ë ìíëìì ììì ëìì(flush)ìë íëë.
+
+
+======================
+CPU ëì ììëë ìë
+======================
+
+íëêëëë CPU ê ëëë ìíëììëì ìíí ììíëë ìíí ì êìëê
+ìêíëë, ëëì, ìë ëì ëìê êì ìëë ìííëë CPU ìê ëêëë:
+
+	a = READ_ONCE(*A);
+	WRITE_ONCE(*B, b);
+	c = READ_ONCE(*C);
+	d = READ_ONCE(*D);
+	WRITE_ONCE(*E, e);
+
+CPU ë êêì ììíëìì ìí ëëë ìíëììì ëì ììíëìì ìëíê
+ìì ìëí êìë ììíê, êë ìí ììí ìëìì êìíêì ìíì ììì
+ìíëììì ìíë êìë ììíëë:
+
+	LOAD *A, STORE *B, LOAD *C, LOAD *D, STORE *E.
+
+
+ëìíìë, ììëë íì ìëìëë.  ëì CPU ëê ìíìëëìì ìì êìì
+ìëíì ëíëë ê ììë ëìê êìëë:
+
+ (*) ëë ìíëììëì ìíì êì íëêê ìí êëë ìëë íìê ìë
+     êìê ëì ëë, ìíì ìíëììëì ìì ëëë ëì ìì ììë ì
+     ììëë;
+
+ (*) ëë ìíëììëì ììììë ìíë ìë ìê, íììëê ìëë
+     êêëì ëëìì íëë;
+
+ (*) ëë ìíëììëì ììììë ìíë ìë ììëë, ììë ìëíì
+     ìíìì ëë ìêì ìì êêê ììì ìë ììëë;
+
+ (*) ëëë ììì ììëì CPU ëìì ììë ì ë ì ììí ì ìëë ìëì
+     ëìë ììëë;
+
+ (*) ëëì ìíìë ììí ìììì ìììëì ìêììë ìëí ì ìë
+     ëëëë I/O íëìì (ëëëì PCI ëëìì ë ë ìê êëí ìë
+     ììëë) ì ëí ììëë êì êë ìíëììì ìí íëìì ìì
+     ëìì ìëê ìí ìíë ìë ììëë; êëê
+
+ (*) íë CPU ì ëìí ììê ììì ìíì ëì ìë ìê, ìì ìêì
+     ëìëìì - ìíìê ììë ììì ëëíëë - ì ëìë ìíìí ìë
+     ììë ì ìêì êëê ëë CPU ëìë êì ììë ìëëëë ëìì
+     ììëë.
+
+ëëì ìì ìëëëí ëë CPU ê ëìë ìë êêë:
+
+	LOAD *A, ..., LOAD {*C,*D}, STORE *E, STORE *B
+
+	("LOAD {*C,*D}" ë ìíë ëëìëë)
+
+
+íìë, CPU ë ììëë ìêìì êì ëìíëë: CPU ìê _ìì_ ì ìììëì
+ìììêë ëëë ëëìì ììë ìíí ìì ììì êìë ëìì êìëë.
+ìë ëì ëìì ìëê ìììëë:
+
+	U = READ_ONCE(*A);
+	WRITE_ONCE(*A, V);
+	WRITE_ONCE(*A, W);
+	X = READ_ONCE(*A);
+	WRITE_ONCE(*A, Y);
+	Z = READ_ONCE(*A);
+
+êëê ìëì ìíì ìí êìì ìëê êìíë, ìì êêë ëìê êì
+ëíë êìëê ììë ì ììëë:
+
+	U == *A ì ìì ê
+	X == W
+	Z == Y
+	*A == Y
+
+ìì ìëë CPU ê ëìì ëëë ììì ìíìë ëëëë íêëë:
+
+	U=LOAD *A, STORE *A=V, STORE *A=W, X=LOAD *A, STORE *A=Y, Z=LOAD *A
+
+íìë, ëëë êìì ìëë, ì ìíìë íëêëì ì ììì ììí
+ìêììëêë ëìëë ëì íì, ìë ìíìëë ëëìì ìë ììë, ê
+ìììëì íììêë ëëì ìë ììëë.  ìë ìííììì CPU ë êì
+ììì ëí ìììì ëë ìíëììëì ìëì í ìë ìê ëëì READ_ONCE()
+ì WRITE_ONCE() ë ìêì ëê ìí ëê ëë íìí ìì íê ëëë, ìë
+ëì, Itanium ììë READ_ONCE() ì WRITE_ONCE() ë ììí volatile ììíì
+GCC ê êê êë ìëìë ëìíë íì ììíëìì ld.acq ì stl.rel
+ììíëìì êê ëëëë íëë.
+
+ìíìë ìì ìíìì ìììëì CPU ê ëêë ìì íìêë ëëêë ëë
+ëëëë ì ììëë.
+
+ìë ëì:
+
+	*A = V;
+	*A = W;
+
+ë ëìê êì ëíë ì ììëë:
+
+	*A = W;
+
+ëëì, ìê ëëìë WRITE_ONCE() ììë, *A ëì V êì ììì íêë
+ìëìëê êìí ì ììëë.  ëìíê:
+
+	*A = Y;
+	Z = *A;
+
+ë, ëëë ëëìë READ_ONCE() ì WRITE_ONCE() ììë ëìê êì ëíë ì
+ììëë:
+
+	*A = Y;
+	Z = Y;
+
+êëê ì LOAD ìíëììì CPU ëêìë ìì ëìì ììëë.
+
+
+êëê ALPHA ê ìë
+--------------------
+
+DEC Alpha CPU ë êì ìíë ëëë ììì CPU ì íëìëë.  êêëë ìëë,
+Alpha CPU ì ìë ëìì ëíë ëìí ììë êìê ììì, ëêì ìëììë
+êêëì ìë ìì ëìì ìë ëë ìêì ìëìí ëë êë íìíëë.
+ìêê ëë ëìí ììì ëëìê ìë íìí ìë ëëìë, ëìí ììì
+ëëìë ëëë ìêì ììíê íê ëê ìì ëëë ëêí íì, íìí ëê
+ê ìëì ëìí ëêì ìëë ììë ììëê íê ëëìëë.
+
+Alpha ë ëëì ìëì ëëë ëëì ëëì ììí ì ììëë.
+
+ìì "ìì ìêì" ìëììì ìêíìì.
+
+
+êì ëì êìí
+----------------
+
+êì ëììì ëìíë êìíëì êìí ììë SMP ìì ìì ìíì ëìë
+íë SMP ìíì ëì ì ììëë.  ìê UP ìëì ììíëì SMP íìíì
+êëëì ëìíë ëìììëë.  ì êììë íì ëëìë ììíì ëìë
+íêí ì ìêìë êë ëëì ëëëì êì ììì íêëì ìëëë.
+
+ì êìë ìëíê íêíê ìí, ëì ëëì virt_mb() ëì ëíëë ììí ì
+ììëë. ìêëì SMP ê íìí ëì ìëë smp_mb() ëê ëìí íêë
+êìëëë, SMP ì SMP ìë ììí ëëì ëí ëìí ìëë ëëìëëë.
+ìë ëì, êì ëì êìíëì (ìëë SMP ì) íìíì ëêíë í ëìë
+smp_mb() ê ìëë virt_mb() ë ììíì íëë.
+
+ìêëì smp_mb() ëì êëê ëë ëëìì ëìíë, íí, MMIO ì ìíì
+ëíìë êìíì ììëë: MMIO ì ìíì ììíëë, íì ëëìëì
+ììíìê ëëëë.
+
+
+=======
+ìì ì
+=======
+
+ìíì ëí
+-----------
+
+ëëë ëëìëì ìíì ëíë ìììì ìëì ììì ëêíì ëì ììíì
+ìê êííëë ììë ì ììëë.  ë ììí ëìì ìíì ëìì ìêíìì:
+
+	Documentation/circular-buffers.txt
+
+
+=========
+ìê ëí
+=========
+
+Alpha AXP Architecture Reference Manual, Second Edition (Sites & Witek,
+Digital Press)
+	Chapter 5.2: Physical Address Space Characteristics
+	Chapter 5.4: Caches and Write Buffers
+	Chapter 5.5: Data Sharing
+	Chapter 5.6: Read/Write Ordering
+
+AMD64 Architecture Programmer's Manual Volume 2: System Programming
+	Chapter 7.1: Memory-Access Ordering
+	Chapter 7.4: Buffering and Combining Memory Writes
+
+IA-32 Intel Architecture Software Developer's Manual, Volume 3:
+System Programming Guide
+	Chapter 7.1: Locked Atomic Operations
+	Chapter 7.2: Memory Ordering
+	Chapter 7.4: Serializing Instructions
+
+The SPARC Architecture Manual, Version 9
+	Chapter 8: Memory Models
+	Appendix D: Formal Specification of the Memory Models
+	Appendix J: Programming with the Memory Models
+
+UltraSPARC Programmer Reference Manual
+	Chapter 5: Memory Accesses and Cacheability
+	Chapter 15: Sparc-V9 Memory Models
+
+UltraSPARC III Cu User's Manual
+	Chapter 9: Memory Models
+
+UltraSPARC IIIi Processor User's Manual
+	Chapter 8: Memory Models
+
+UltraSPARC Architecture 2005
+	Chapter 9: Memory
+	Appendix D: Formal Specifications of the Memory Models
+
+UltraSPARC T1 Supplement to the UltraSPARC Architecture 2005
+	Chapter 8: Memory Models
+	Appendix F: Caches and Cache Coherency
+
+Solaris Internals, Core Kernel Architecture, p63-68:
+	Chapter 3.3: Hardware Considerations for Locks and
+			Synchronization
+
+Unix Systems for Modern Architectures, Symmetric Multiprocessing and Caching
+for Kernel Programmers:
+	Chapter 13: Other Memory Models
+
+Intel Itanium Architecture Software Developer's Manual: Volume 1:
+	Section 2.6: Speculation
+	Section 4.4: Memory Access
-- 
1.9.1