转:http://blog.chinaunix.net/uid-25871104-id-2880884.html
摘抄memory-barrier.txt中关于mmiowb的一部分,以解答mmiowb的用法。
----------
在某些情况下(特别是涉及到NUMA的情况), 两个CPU上发起的属于两个spinlock临界区的IO
访问可能被PCI桥看成是交错发生的, 因为PCI桥并不一定参与cache一致性协议, 以至于无
法响应读内存屏障.
例如:
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
这可能会引起硬件操作的错误.
这里所需要的是, 在释放spinlock之前, 使用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的两次STORE操作先于CPU 2的STORE操作被PCI桥所看到.
此外, 对于同一硬件设备在进行STORE操作之后再进行LOAD操作, 可以省去mmiowb(), 因为
LOAD操作将强制STORE操作在开始LOAD之前就完成:
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);