Assembly 锁前缀的范围是什么?
据说以“lock”为前缀的汇编指令是原子指令。我想知道“锁”是否只能影响一条汇编指令;汇编指令本身不是原子指令吗 以下是linux内核中原子函数的示例:Assembly 锁前缀的范围是什么?,assembly,linux-kernel,x86,kernel,Assembly,Linux Kernel,X86,Kernel,据说以“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)
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可以被中断吗?只有极少数特定的汇编指令是原子指令。x86在很大程度上是一种CISC体系结构,这意味着单个指令可以完成大量工作,其中单个指令可以将值从内存地址加载到寄存器中,对其执行操作,然后将结果存储回内存。这是一个复杂的操作,需要很多时间和CPU周期来执行;为了提高性能,许多这样的指令是流水线的,它们的执行顺序是相互交织的
基本上,汇编语言和其他语言一样。特别是在谈到CISC体系结构时,有许多“高级”构造和操作可以在单个命令中执行,除非在指令文档中或使用
lock
修饰符明确指定,否则不能保证它们以原子方式执行。对于在其他CPU内核上同时运行的其他指令,指令不是原子的。LOCK
前缀的作用是锁定总线,以便在锁定的指令运行时,其他内核无法访问内存,从而防止两个内核试图同时访问同一位置时发生冲突。锁定前缀影响单个指令
当指令修改多个CPU之间共享的内存时,它们就不再是原子指令。涉及读取内存操作数、对其执行某些操作(如AND、XOR、INC等)然后将其写回的修改不会被其他CPU视为原子修改。锁定前缀“锁定”内存位置,因此3个步骤(读取、修改、写入)看起来是一个步骤,即其他CPU只能观察锁定指令之前和之后的内容
请参阅英特尔或AMD的官方CPU文档
编辑:在您新添加的示例中,如果我们讨论的是中断,则这些指令都不能被中断。中断发生在整个指令之间。锁定前缀使
sub
指令原子化。sete
指令不是原子指令,它用于将ZF
标志转换为零或非零整数值。我为这个问题添加了一个示例。我的意思是两条指令之间是否会发生中断?是的,它们可以。这有什么问题吗?AlexeyFrunze:我猜@venus.w担心两条指令之间的中断可能会违反标志寄存器,导致ste结果错误。但实际上,当中断返回时,标志寄存器将被恢复。