3

我正在将内核扩展移植到多处理器 PowerPC 上的 32/64 位 AIX,用 C 编写。我只需要原子读取操作和原子写入操作(我不需要获取和添加,比较-and-swap 等)只是为了澄清一下:对我来说,“原子性”不仅意味着“没有交错”,还意味着“跨多个核心的可见性”。这些操作对指针进行操作,因此对“int”变量的操作对我来说毫无用处。

如果我声明变量“volatile”,C 标准说该变量可以被未知因素修改,因此不受优化。

从我读到的,似乎常规的读写应该是非交错的,而且linux 内核源似乎也同意。它说:

__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)例如)。

所以我的问题是:

  1. 声明变量'volatile'是否足以实现可见性和无交错意义上的读写原子性?

  2. 如果 1 的答案是“否”,那么这种原子性是如何实现的?

  3. Linux PowerPC 原子实现中的“%U0%X0”是什么意思?

4

2 回答 2

1

GCC 内联汇编语法有一些特点。

在行中,

__asm__ __volatile__("stw%U0%X0 %1,%0" : "=m"(v->counter) : "r"(i));

them是输出操作数, ther是输入操作数。%1 和 %0 指的是参数顺序 (0->m, 1->r)

stw汇编指令有 2 个参数,%U0%X0 是对参数的约束。这些约束是迫使 GCC 分析论点并确保您不会做一些愚蠢的事情。事实证明,'U' 是特定于 powerpc 的(我已经习惯了 X64 约束集:)。可以在以下位置找到完整的约束列表:

http://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html#Machine-Constraints

于 2011-08-25T05:22:39.747 回答
0

我设法回答了问题 1 和 2,但没有回答 3:

  1. 不,还不够。
  2. 仍然需要内存屏障。我使用了 __lwsync() 中内置的 XLC。这既可以防止处理器重新排序,又可以将更改发布到其他处理器。
于 2011-07-27T17:15:03.327 回答