You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

请求基于UMONITOR/UMWAIT的自旋等待锁汇编实现示例

基于UMONITOR/UMWAIT指令的自旋锁汇编实现

在《Intel 64和IA-32架构优化参考手册》中,Intel提供了基于PAUSE指令的自旋等待循环示例(示例11-4. 自旋等待循环与PAUSE指令),但对于UMONITOR/UMWAIT指令,仅提及相关特性(如“支持用户级低功耗低延迟自旋循环指令UMWAIT/UMONITOR和TPAUSE”、“UMWAIT/UMONITOR/TPAUSE指令可降低用户级自旋循环功耗”),并未给出具体实现示例。这些新指令随Intel 2020年9月推出的Tremont微架构(Elkhart Lake平台)发布。

以下是基于PAUSE指令的参考实现(可通过nasm -f win64编译):

section .text

; 暴露两个全局函数:(1) SpinWaitAndAquireLock; (2) ReleaseLock.

cLockByteLocked     equ 0FFh
cLockByteAvailable  equ 0

; 等待锁字节变为可用并获取锁
global SpinWaitAndAquireLock

; 释放之前通过SpinWaitAndAquireLock获取的锁
global ReleaseLock

SpinWaitAndAquireLock:
; 输入: rcx - 同步变量锁字节的地址
   mov  eax, cLockByteLocked ; 将“已锁定”值加载到al;使用eax清除高位以避免对现有eax值的虚假依赖,rax的32-63位也会被清零
   jmp  @FirstCompare
@NormalLoadLoop:
   pause  
@FirstCompare:
; 使用“test, test-and-set”技术
   cmp  [rcx], al   ; 先尝试普通加载而非锁定加载 - 这是“test, test-and-set”的第一步
   je   @NormalLoadLoop ; 静态分支预测中,向后跳转意味着“大概率发生”
   lock xchg [rcx], al  ; 普通加载显示同步变量可用,尝试锁定加载并存储(“test-and-set”)
   cmp  al, cLockByteLocked
   je   @NormalLoadLoop
   ret

ReleaseLock:
; 输入: rcx - 同步变量锁字节的地址
   mov   byte [rcx], cLockByteAvailable ; 直接使用普通存储
   ret 

基于UMONITOR/UMWAIT指令的64位实现(Win64调用约定)

UMONITOR用于设置监控的内存地址,UMWAIT则让CPU进入低功耗状态,直到监控地址被修改或超时。以下是适配字节锁变量的实现:

section .text

cLockByteLocked     equ 0FFh
cLockByteAvailable  equ 0

global SpinWaitAndAquireLock_UMWAIT
global ReleaseLock

; 检查CPU是否支持UMONITOR/UMWAIT的辅助函数(建议在调用前检测)
CheckUMWAITSuport:
    mov eax, 7
    xor ecx, ecx
    cpuid
    test ebx, (1 << 5) ; 检查EBX第5位是否置位(UMONITOR/UMWAIT支持位)
    jnz @Supported
    xor eax, eax
    ret
@Supported:
    mov eax, 1
    ret

SpinWaitAndAquireLock_UMWAIT:
; 输入: rcx - 锁字节地址
    mov eax, cLockByteLocked
    ; 首次尝试获取锁
    cmp byte [rcx], al
    je @EnterUMWaitLoop
    lock xchg byte [rcx], al
    cmp al, cLockByteLocked
    jne @Acquired

@EnterUMWaitLoop:
    ; 设置UMONITOR监控锁地址
    mov rdx, rcx       ; RDX = 监控地址(64位模式下,UMONITOR使用RDX传地址)
    xor ecx, ecx       ; ECX = 监控范围(0表示仅监控指定地址的1字节)
    umonitor

@UMWaitRetry:
    ; 进入UMWAIT,设置超时为无限(EAX=0,EBX=0表示无超时)
    xor eax, eax
    xor ebx, ebx
    umwait
    ; 被唤醒后,再次尝试获取锁
    cmp byte [rcx], al
    je @UMWaitRetry
    lock xchg byte [rcx], al
    cmp al, cLockByteLocked
    je @EnterUMWaitLoop

@Acquired:
    ret

ReleaseLock:
; 输入: rcx - 锁字节地址
    mov byte [rcx], cLockByteAvailable
    ret

关键说明:

  • UMONITOR指令:64位模式下通过RDX指定监控的内存地址,ECX设为0表示仅监控1字节范围。
  • UMWAIT指令:EAX和EBX设为0表示无限等待,直到监控地址被写入触发唤醒,也可设置具体超时周期。
  • CPU支持检测:建议调用自旋锁前先通过CheckUMWAITSuport检测CPU兼容性,避免在不支持的平台执行非法指令。
  • 低功耗优势:相比PAUSE的忙等逻辑,UMWAIT会让CPU进入低功耗状态,大幅降低自旋期间的功耗,同时保持较低的唤醒延迟。

内容的提问来源于stack exchange,提问作者Maxim Masiutin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 22:05:28