3

据说以“lock”为前缀的汇编指令是原子的。我想知道“锁”是否只能影响一条汇编指令;汇编指令本身不是原子的吗?

以下是 linux 内核中的原子函数示例:

static __inline__ int atomic_sub_and_test(int i, atomic_t *v)
 { unsigned char c;
 __asm__ __volatile__(
 LOCK "subl %2,%0; sete %1" 
    :"=m" (v->counter), "=qm" (c) 
     :"ir" (i), "m" (v->counter) : "memory"); 
return c; }

在这个例子中 subl 和 sete 可以被打断吗?

4

3 回答 3

8

锁定前缀影响单个指令。

指令在修改多个 CPU 之间共享的内存时不再是原子的。涉及读取内存操作数、对其执行某些操作(例如 AND、XOR、INC 等)然后将其写回的修改不会被其他 CPU 视为原子操作。锁定前缀“锁定”了内存位置,因此 3 个步骤(读取、修改、写入)看起来是一个,即其他 CPU 只能观察锁定指令之前和之后的内容。

请参阅 Intel 或 AMD 的官方 CPU 文档。

编辑:在您新添加的示例中,如果我们谈论的是中断,这些指令都不能被中断。中断发生在整个指令之间。锁定前缀使sub指令具有原子性。该sete指令不是原子的,它可以将ZF标志转换为零或非零整数值。

于 2012-07-07T03:42:15.773 回答
4

相对于在其他 CPU 内核上同时运行的其他指令而言,一条指令不是原子的。前缀的LOCK作用是锁定总线,以便在锁定指令运行时其他内核无法访问内存,从而防止两个内核尝试同时访问同一位置的冲突。

于 2012-07-07T03:41:10.780 回答
3

只有极少数特定的汇编指令是原子的。x86 在很大程度上是一种 CISC 架构,这意味着单条指令可以完成大量工作,其中单条指令可以将内存地址中的值加载到寄存器中,对其执行操作,然后将结果存储回内存中。这是一个复杂的操作,需要很多时间和 CPU 周期来执行;为了提高性能,许多这样的指令都是流水线的,它们的执行顺序是交织在一起的。

基本上,汇编是一门与其他语言一样的语言。特别是在谈到 CISC 架构时,可以在单个命令中执行许多“高级”构造和操作,除非在指令文档或lock修饰符中明确指定,否则它们不能保证原子执行。

于 2012-07-07T03:41:08.333 回答