【问题标题】:What is the scope of lock prefix?锁前缀的范围是什么?
【发布时间】:2012-07-07 11:51:13
【问题描述】:

据说以“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 可以被打断吗?

【问题讨论】:

    标签: assembly linux-kernel x86 kernel


    【解决方案1】:

    锁定前缀影响单个指令。

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

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

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

    【讨论】:

    • 我已经为这个问题添加了一个例子。
    • 我的意思是两条指令之间可以发生中断吗?
    • 是的,他们可以。这有什么问题吗?
    • AlexeyFrunze:我猜@venus.w 担心两条指令之间发生中断可能会违反标志寄存器并导致 ste 结果错误。但实际上,当中断返回时,标志寄存器会被恢复。
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-29
        • 2011-02-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多