Chinese translated version of Linux/Documentation/io_ordering.txt
If you have any comment or update to the content, please contact theoriginal document maintainer directly. However, if you have a problem communicating in English you can also ask the Chinese maintainer forhelp. Contact the Chinese maintainer if this translation is outdatedor if there is a problem with the translation. Chinese maintainer: 张凯 zhangking520@gmail.com ---------------------------------------------------------------------
Linux/Documentation/io_ordering.txt 的中文翻译 如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文 交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻 译存在问题,请联系中文版维护者。 中文版维护者:张凯 zhangking520@gmail.com 中文版翻译者: 张凯 zhangking520@gmail.com 以下为正文 ---------------------------------------------------------------------
On some platforms, so-called memory-mapped I/O is weakly ordered. On such
platforms, driver writers are responsible for ensuring that I/O writes to
memory-mapped addresses on their device arrive in the order intended. This is
typically done by reading a 'safe' device or bridge register, causing the I/O
chipset to flush pending writes to the device before any reads are posted. A
driver would usually use this technique immediately prior to the exit of a
critical section of code protected by spinlocks. This would ensure that
subsequent writes to I/O space arrived only after all prior writes (much like a
memory barrier op, mb(), only with respect to I/O).
在一些平台上,所谓的io内存映射不是有序的。在这样的平台,驱动程序编写者有责任确保I / O写入
他们的设备上的内存映射地址到达的顺序。这是通常是通过阅读“安全”设备或桥梁寄存器,导致I/ O
芯片组刷新等待写入到设备之前读取时间。 驱动程序通常会立即使用这种技术出口的前旋锁保护的代码的关键部分。
这将确保后续写入I / O空间后,才抵达之前写(很像的内存屏障运算,MB(),只涉及到I / O)。
A more concrete example from a hypothetical device driver: 一个具体的例子来自一个虚构的设备驱动 ... CPU A: spin_lock_irqsave(&dev_lock, flags) CPU A: val = readl(my_status); CPU A: ... CPU A: writel(newval, ring_ptr); CPU A: spin_unlock_irqrestore(&dev_lock, flags) ... CPU B: spin_lock_irqsave(&dev_lock, flags) CPU B: val = readl(my_status); CPU B: ... CPU B: writel(newval2, ring_ptr); CPU B: spin_unlock_irqrestore(&dev_lock, flags) ... In the case above, the device may receive newval2 before it receives newval, which could cause problems. Fixing it is easy enough though: 上面的例子,设备可能在接受地一个变量前,收到第二个变量,而引起问题。下面是解决方案 ... CPU A: spin_lock_irqsave(&dev_lock, flags) CPU A: val = readl(my_status); CPU A: ... CPU A: writel(newval, ring_ptr); CPU A: (void)readl(safe_register); /* maybe a config register? */ CPU A: spin_unlock_irqrestore(&dev_lock, flags) ... CPU B: spin_lock_irqsave(&dev_lock, flags) CPU B: val = readl(my_status); CPU B: ... CPU B: writel(newval2, ring_ptr); CPU B: (void)readl(safe_register); /* maybe a config register? */ CPU B: spin_unlock_irqrestore(&dev_lock, flags) Here, the reads from safe_register will cause the I/O chipset to flush any pending writes before actually posting the read to the chipset, preventing possible data corruption.
这里,从安全寄存器读取会导致I/ O芯片组,来清除任何挂起的写入操作,在实际上张贴读的芯片组前,以防止可能的数据损坏。