Re: [PATCH v1] docs/zh_CN: add zh_CN translation for memory-barriers.txt

From: Leo Yan
Date: Sat Aug 19 2023 - 12:25:41 EST


Hi,

On Fri, Aug 11, 2023 at 02:22:55PM +0800, Gang Li wrote:
> Add new zh translation zh_CN/memory-barrier.txt based on v6.5-rc5.
>
> Signed-off-by: Gang Li <gang.li@xxxxxxxxx>
> ---
> .../translations/zh_CN/memory-barriers.txt | 2458 +++++++++++++++++
> 1 file changed, 2458 insertions(+)
> create mode 100644 Documentation/translations/zh_CN/memory-barriers.txt
>
> diff --git a/Documentation/translations/zh_CN/memory-barriers.txt
> b/Documentation/translations/zh_CN/memory-barriers.txt
> new file mode 100644
> index 000000000000..caa2775cc9c6
> --- /dev/null
> +++ b/Documentation/translations/zh_CN/memory-barriers.txt
> @@ -0,0 +1,2458 @@
> +译注:
> +本文仅为方便汉语阅读,不保证与英文版本同步;
> +若有疑问,请阅读英文版本;
> +若有翻译问题,请通知译者;
> +若想修改文档,也请先修改英文版本。
> +
> + ============================
> + Linux 内核内存屏障
> + ============================
> +
> +作者:David Howells <dhowells@xxxxxxxxxx>
> + Paul E. McKenney <paulmck@xxxxxxxxxxxxx>
> + Will Deacon <will.deacon@xxxxxxx>
> + Peter Zijlstra <peterz@xxxxxxxxxxxxx>
> +
> +译者:李港 Gang Li <gang.li@xxxxxxxxx>
> +
> +==========
> +免责声明
> +==========
> +
> +本文档不是一个规范;它由于有意 (为了简洁) 或无意 (由于人为因素)
> 的原因而不完整。本文档
> +旨在指导如何使用 Linux 提供的各种内存屏障,如果有疑问
> (而且有很多),请在邮件列表咨询。
> +一些疑问可以通过参考正式的内存一致性模型和 tools/memory-model/
> 下的相关文档来解决。
> +这些内存模型是维护者的集体意见,而不是准确无误的实现规范。
> +
> +再次重申,本文档不是 Linux 对硬件的规范或期望。

再次重申,本文档不是 Linux 对硬件要求的规范手册。

> +本文档的目的有两个:
> +
> + (1) 为内核屏障函数指定可以依赖的最小功能,以及

(1) 针对任何一个特定的屏障,定义其可依赖的最小功能;

> +
> + (2) 提供关于如何使用屏障的指南。

(2) 对于可用的屏障,提供如何使用的指南。

> +
> +请注意,一个架构可以为任何屏障提供超出最低要求的功能,但是,如果架构提供的功能少于最低
> +要求,则该架构是错误的。

... 一个架构可以为任何特定的屏障实现超出最低要求的功能 ...

> +
> +还要注意的是,在某些架构中,部分屏障可能是空操作。因为该架构已经保证了该内存序,使得
> +显式屏障是不必要的。

还要注意,在某些架构中,一个屏障可能是空操作。这是因为这些架构的工作
方式不再需要显式地使用屏障了。

> +
> +========
> +目录
> +========
> +
> + (*) 抽象内存访问模型。
> +
> + - 设备操作。
> + - CPU 的保证。
> +
> + (*) 什么是内存屏障?
> +
> + - 内存屏障的种类。
> + - 关于内存屏障不可假设什么?
> + - 地址依赖屏障 (旧) 。
> + - 控制依赖。
> + - SMP 屏障配对。
> + - 内存屏障序列示例。
> + - 读屏障与预读。

s/预读/读取预测

> + - 多拷贝原子性。
> +
> + (*) 显式内核屏障函数。
> +
> + - 编译器屏障。
> + - CPU 内存屏障。
> +
> + (*) 隐式内核屏障函数。
> +
> + - 取锁函数。

锁获取函数。

> + - 关中断函数。
> + - 睡眠和唤醒函数。
> + - 其他函数。
> +
> + (*) 跨CPU ACQUIRING 屏障的影响。
> +
> + - Acquires 与 内存访问。
> +
> + (*) 哪里需要内存屏障?
> +
> + - 处理器间交互。
> + - 原子操作。
> + - 访问设备。
> + - 中断。
> +
> + (*) 内核 I/O 屏障。
> +
> + (*) 假想的最小执行顺序模型。

s/假想/预设 ?

> +
> + (*) CPU 缓存的影响。
> +
> + - 缓存一致性。
> + - 缓存一致性与 DMA。
> + - 缓存一致性与 MMIO。
> +
> + (*) CPU 相关。
> +
> + - 还有就是Alpha。
> + - 虚拟机客户端。
> +
> + (*) 使用示例。
> +
> + - 环形缓冲区。
> +
> + (*) 参考资料。
> +
> +============================
> +抽象内存访问模型
> +============================
> +
> +考虑以下抽象模型:
> +
> + : :
> + : :
> + : :
> + +-------+ : +--------+ : +-------+
> + | | : | | : | |
> + | | : | | : | |
> + | CPU 1 |<----->| 内存 |<----->| CPU 2 |

Unalignment caused by extra space around "内存".

> + | | : | | : | |
> + | | : | | : | |
> + +-------+ : +--------+ : +-------+
> + ^ : ^ : ^
> + | : | : |
> + | : | : |
> + | : v : |
> + | : +--------+ : |
> + | : | | : |
> + | : | | : |
> + +---------->| 设备 |<----------+
> + : | | :
> + : | | :
> + : +--------+ :
> + : :
> +
> +每个 CPU 执行一个访存程序。在本文的抽象 CPU 中,访问指令的顺序非常松散,每个

s/访问指令的顺序非常松散/访问操作可以是完全乱序的/

Here we need to take care the subtle difference between the "memory
instructions ordering" vs "memory operations ordering".


> CPU 可以

Unintended new line.

> +按照任意顺序执行访存指令,每个 CPU

s/访存指令/访存操作/

> 都保证在本核心看来,最终执行结果与不乱序的情况相同。
> +同样,编译器也可以按照任意顺序排列指令,只要不影响程序的运行结果。
> +
> +CPU可以通过一些本地缓存来提高指令运行效率,内存操作会被缓存在当前CPU上,每个
> CPU 都能
> +按顺序看到自己的内存操作。但每个缓存项写入到主存的顺序未知,在上图中,即每条指令的结果穿过
> +虚线的顺序未知。

Here cannot match with the original words:

"So in the above diagram, the effects of the memory operations performed by a
CPU are perceived by the rest of the system as the operations cross the
interface between the CPU and rest of the system (the dotted lines)."

在上图中,当一个CPU执行内存操作后,其结果可以被系统中其他硬件所感知,
这需要通过在CPU和系统其他模块的接口(虚线所示)之间的额外操作来完成。

> +
> +
> +例如,考虑以下内存操作序列:
> +
> + CPU 1 CPU 2
> + =============== ===============
> + { A == 1; B == 2 }
> + A = 3; x = B;
> + B = 4; y = A;
> +
> +CPU 外部可能看到如下任意顺序:

CPU 外部可能看到如下任意顺序, 其排列组合共有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向内存进行写操作,而另外一个CPU在执行读操作,进行读操作的CPU
感知(或者观察到)的数据顺序,有可能和写操作(Stores)的顺序是不同的。

> +
> +
> +再举一个例子,考虑这个序列:
> +
> + 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) 和 (D == 1)
> + (Q == &B) 和 (D == 2)
> + (Q == &B) 和 (D == 4)
> +
> +请注意,CPU 2 永远不会 将 C 的值写入 D,因为 CPU 会在读 *Q 前将 P 赋值给
> Q。
> +
> +
> +设备操作
> +-----------------
> +
> +有些设备是通过将自己的寄存器映射到内存来控制的,访问控制寄存器的顺序非常重要。假设一个

一些设备提供了一组访存地址空间,用于访问设备的控制接口(例如寄存器),
那么访问控制寄存器的顺序非常重要。例如,我们想象一个网卡,需要通过其
地址端口寄存器 (A) 和数据端口寄存器 (D)来访问内部寄存器。

> +网卡有一组通过地址端口寄存器 (A) 和数据端口寄存器 (D) 访问的内部寄存器。
> +要读取 5 号内部寄存器,可以使用以下代码:
> +
> + *A = 5;
> + x = *D;
> +
> +可能有两种执行顺序:
> +
> + STORE *A = 5, x = LOAD *D
> + x = LOAD *D, STORE *A = 5
> +
> +其中第二个序列几乎肯定会导致故障,因为先读后写。

... 因为地址的设置是在读取寄存器之后才完成的。


I stop here in today and will continue to review this doc.

Thanks for doing this!

Leo