gpt4 book ai didi

assembly - 使用 XCHG 解锁的自旋锁

转载 作者:行者123 更新时间:2023-12-01 18:55:38 25 4
gpt4 key购买 nike

维基百科提供的使用 x86 XCHG 命令的自旋锁的示例实现是:

; Intel syntax

locked: ; The lock variable. 1 = locked, 0 = unlocked.
dd 0

spin_lock:
mov eax, 1 ; Set the EAX register to 1.

xchg eax, [locked] ; Atomically swap the EAX register with
; the lock variable.
; This will always store 1 to the lock, leaving
; the previous value in the EAX register.

test eax, eax ; Test EAX with itself. Among other things, this will
; set the processor's Zero Flag if EAX is 0.
; If EAX is 0, then the lock was unlocked and
; we just locked it.
; Otherwise, EAX is 1 and we didn't acquire the lock.

jnz spin_lock ; Jump back to the MOV instruction if the Zero Flag is
; not set; the lock was previously locked, and so
; we need to spin until it becomes unlocked.

ret ; The lock has been acquired, return to the calling
; function.

spin_unlock:
mov eax, 0 ; Set the EAX register to 0.

xchg eax, [locked] ; Atomically swap the EAX register with
; the lock variable.

ret ; The lock has been released.

从这里开始https://en.wikipedia.org/wiki/Spinlock#Example_implementation

我不明白为什么解锁需要是原子的。出了什么问题

spin_unlock:
mov [locked], 0

最佳答案

解锁确实需要have release semantics才能正确保护关键部分。但它不需要顺序一致性。原子性并不是真正的问题(见下文)。

所以,是的,在 x86 上,一个简单的存储是安全的,并且 glibc's pthread_spin_unlock does so: :

    movl    $1, (%rdi)
xorl %eax, %eax
retq

另请参阅一个简单但可能可用的 x86 spinlock implementation I wrote in this answer ,它使用带有 pause 指令的只读自旋循环。

<小时/>

该代码可能是根据位字段版本改编的。

使用 btr 解锁位域中的一个标志将其归零并不安全,因为它是对包含字节 (or the containing naturally-aligned 4 byte dword or 2 byte word) 的非原子读取-修改-写入。

所以也许写它的人没有意识到 simple stores to aligned addresses are atomic on x86, like on most ISAs 。但 x86 具有弱序 ISA 所不具备的特点,那就是每个存储区都有 release semantics 。用于释放锁的 xchg 使每次解锁都成为完整的内存屏障,这超出了正常的锁定语义。 (尽管在 x86 上,获取锁将是一个完全障碍,因为没有 xchg 或其他 lock 就无法执行原子 RMW 或原子比较和交换ed 指令,这些都是像 mfence 这样的完整屏障。)

解锁存储在技术上不需要是原子的,因为我们只存储零或1,所以只有低字节重要。例如我认为如果锁未对齐并跨缓存行边界分割,它仍然可以工作。撕裂可能会发生,但并不重要,真正发生的是锁的低字节被原子地修改,操作总是将零放入高 3 个字节。

<小时/>

如果你想返回旧值来捕获双重解锁错误,更好的实现是单独加载和存储:

spin_unlock:
;; pre-condition: [locked] is non-zero

mov eax, [locked] ; old value, for debugging
mov dword [locked], 0 ; On x86, this is an atomic store with "release" semantics.

;test eax,eax
;jz double_unlocking_detected ; or leave this to the caller
ret

关于assembly - 使用 XCHG 解锁的自旋锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36731166/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com