据说以“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可以被中断吗?
答案 0 :(得分:8)
锁定前缀会影响单个指令。
当修改多个CPU之间共享的内存时,指令停止是原子的。涉及读取内存操作数,对其执行某些操作(例如AND,XOR,INC等)然后将其写回的修改不被其他CPU视为原子操作。锁定前缀“锁定”内存位置,因此3个步骤(读取,修改,写入)看起来像一个,即其他CPU只能观察锁定指令之前和之后的内容。
请参阅Intel或AMD的官方CPU文档。
编辑:在您新添加的示例中,如果我们正在讨论中断,那么这些指令都不会被中断。整个指令之间发生中断。锁前缀使sub
指令成为原子。 sete
指令不是原子的,而是将ZF
标志转换为零或非零整数值。
答案 1 :(得分:4)
对于在其他CPU核心上并发运行的其他指令,指令不是原子的。 LOCK
前缀的作用是锁定总线,以便在锁定指令运行时其他内核无法访问内存,从而防止两个内核同时尝试访问同一位置时发生冲突。
答案 2 :(得分:3)
只有极少数某些装配指令是原子的。 x86主要是CISC架构,这意味着单个指令可以完成很多工作,其中单个指令可以将值从内存地址加载到寄存器中,对其执行操作,然后将结果存回在记忆中。这是一个复杂的操作,需要花费很多时间和CPU周期来执行;为了提高性能,许多这样的指令都是流水线的,它们的执行顺序是交织在一起的。
基本上,汇编是一种与其他语言一样的语言。特别是在谈到CISC架构时,有许多“高级”构造和操作可以在单个命令中执行,它们不能保证原子执行,除非在指令文档中明确指定或使用{{ 1}}修饰符。