【发布时间】:2011-09-29 16:53:22
【问题描述】:
我正在将内核扩展移植到多处理器 PowerPC 上的 32/64 位 AIX,用 C 编写。我只需要原子读取操作和原子写入操作(我不需要 fetch-and-添加,比较和交换等) 澄清一下:对我来说,“原子性”不仅意味着“没有交错”,还意味着“跨多核的可见性”。 这些操作对指针进行操作,因此对“int”变量的操作对我来说毫无用处。
如果我声明变量“volatile”,C 标准说该变量可以被未知因素修改,因此不受优化。
根据我的阅读,似乎常规的读写应该是非交错的,linux kernel souces 似乎也同意。它说:
__asm__ __volatile__("stw%U0%X0 %1,%0" : "=m"(v->counter) : "r"(i));
stw 是“存储字”,据说是原子的,但我不知道“%U0%X0”是什么意思。我不明白这个汇编指令如何强加可见性。
当我编译我的内核扩展时,'std' 用于我想要的分配,但从我读到的内容,它对于 64 位机器也应该是原子的。我对 PowerPC 及其指令集的细节知之甚少,但是我在编译文件的汇编列表中没有找到任何内存屏障指令(“sync”或“eieio”)。
内核提供了 fetch_and_addlp() 服务,可以用来实现原子读取(例如v = fetch_and_addlp(&x, 0))。
所以我的问题是:
声明变量'volatile'是否足以实现可见性和非交错意义上的读写原子性?
如果 1 的答案是“否”,那么这种原子性是如何实现的?
Linux PowerPC原子实现中的“%U0%X0”是什么意思?
【问题讨论】:
-
那不是“原子”的意思!如果您想要订购保证,请使用内存屏障。 (或者只是使用锁,因为显然每个人都弄错了障碍。)
-
@tc:不幸的是,微处理器社区对“原子”一词的含义并不一致。当我大约在 1991 年定义 Intel x86 内存排序架构时,我使用了 tc 使用的定义——“原子”指的是看到一个操作全部完成或根本没有完成,永远不会半途而废,而“内存排序”则是另一回事。然而,ARM 最近使用“原子”来指代内存排序,“单一位置原子性”指代 tc 和我称之为“原子”的东西,而“多位置原子性”或“写入原子性”指代内存排序系统的属性。