我阅读了英特尔手册,发现指令有一个锁定前缀,可以防止处理器同时写入相同的内存位置。我对此感到非常兴奋。我想它可以用作硬件互斥锁。所以我写了一段代码来试一试。结果相当令人沮丧。该锁不支持 MOV 或 LEA 指令。手册上说 LOCK 只支持 ADD、ADC、AND、BTC、BTR、BTS、CMPXCHG、CMPXCH8B、DEC、INC、NEG、NOT、OR、SBB、SUB、XOR、XADD 和 XCHG。更重要的是,如果 LOCK 前缀与这些指令之一一起使用并且源操作数是内存操作数,则可能会生成未定义的操作码异常 (#UD)。
我想知道为什么这么多限制,这么多限制让 LOCK 看起来毫无用处。我不能用它来保证一般的写操作没有脏数据或其他由并行引起的问题。
例如,我在 C 中编写了代码 ++(*p)。p 是指向共享内存的指针。对应的程序集如下:
movl 28(%esp), %eax
movl (%eax), %eax
leal 1(%eax), %edx
movl 28(%esp), %eax
movl %edx, (%eax)
我在“movl”和“leal”之前添加了“lock”,但处理器抱怨“Invalid Instruction”。:-( 我想使写操作序列化的唯一方法是使用软件互斥锁,对吧?