作者:梦幻小螳螂 | 来源:互联网 | 2023-05-27 19:03
在Intel的文档称
该指令可以与LOCK
前缀一起使用,以允许指令以原子方式执行.
我的问题是
可以CMPXCHG
用内存地址操作吗?从文档看来似乎没有,但任何人都可以确认只能在寄存器中使用实际的VALUE,而不是内存地址吗?
如果CMPXCHG
不是原子级和高级语言级CAS必须通过LOCK CMPXCHG
(带LOCK
前缀)来实现,那么引入这样一条指令的目的是什么?
Peter Cordes..
23
这似乎是你真正要求的一部分:
为什么不使用内存操作数lock
隐含前缀cmpxchg
,就像它一样xchg
?
简单的答案(其他人给出的)就是英特尔以这种方式设计它.但这导致了一个问题:
为什么英特尔这样做?是否有一个用例的cmpxchg
不lock
?
在单CPU系统上,相对于其他线程或在同一CPU内核上运行的任何其他代码cmpxchg
是原子的.(但不是"系统"观察者,如内存映射I/O设备,或者是正常内存的DMA读取设备,因此lock cmpxchg
即使在单处理器CPU设计上也是如此).
上下文切换只能发生在中断上,中断发生在指令之前或之后,而不是在中间.在同一CPU上运行的任何代码都会将其cmpxchg
视为完全执行或根本不执行.
例如,Linux内核通常使用SMP支持进行编译,因此它lock cmpxchg
用于原子CAS.但是当在单处理器系统上启动时,它会将lock
前缀修补到nop
代码内联的任何地方,因为nop
cmpxchg
运行速度比快lock cmpxchg
.有关更多信息,请参阅此LWN有关Linux的"SMP替代"系统的文章.它甚至可以lock
在热插拔第二个CPU之前修补回前缀.
在这个答案中阅读更多关于单处理器系统上单个指令的原子性的信息,并在@ supercat的答案+注释中可以num++
是原子的int num
.请参阅我的答案,了解有关原子性如何实现/为读 - 修改 - 写指令实现的大量详细信息lock cmpxchg
.
(同样的推理也适用于cmpxchg8b
/ cmpxchg16b
,并且xadd
通常仅用于同步/原子操作,而不是使单线程代码运行得更快.显然,内存目的地add [mem], reg
在lock add [mem], reg
案例之外是有用的.)
1> Peter Cordes..:
这似乎是你真正要求的一部分:
为什么不使用内存操作数lock
隐含前缀cmpxchg
,就像它一样xchg
?
简单的答案(其他人给出的)就是英特尔以这种方式设计它.但这导致了一个问题:
为什么英特尔这样做?是否有一个用例的cmpxchg
不lock
?
在单CPU系统上,相对于其他线程或在同一CPU内核上运行的任何其他代码cmpxchg
是原子的.(但不是"系统"观察者,如内存映射I/O设备,或者是正常内存的DMA读取设备,因此lock cmpxchg
即使在单处理器CPU设计上也是如此).
上下文切换只能发生在中断上,中断发生在指令之前或之后,而不是在中间.在同一CPU上运行的任何代码都会将其cmpxchg
视为完全执行或根本不执行.
例如,Linux内核通常使用SMP支持进行编译,因此它lock cmpxchg
用于原子CAS.但是当在单处理器系统上启动时,它会将lock
前缀修补到nop
代码内联的任何地方,因为nop
cmpxchg
运行速度比快lock cmpxchg
.有关更多信息,请参阅此LWN有关Linux的"SMP替代"系统的文章.它甚至可以lock
在热插拔第二个CPU之前修补回前缀.
在这个答案中阅读更多关于单处理器系统上单个指令的原子性的信息,并在@ supercat的答案+注释中可以num++
是原子的int num
.请参阅我的答案,了解有关原子性如何实现/为读 - 修改 - 写指令实现的大量详细信息lock cmpxchg
.
(同样的推理也适用于cmpxchg8b
/ cmpxchg16b
,并且xadd
通常仅用于同步/原子操作,而不是使单线程代码运行得更快.显然,内存目的地add [mem], reg
在lock add [mem], reg
案例之外是有用的.)
2> Holger..:
您正在将高级锁与正好命名的低级CPU功能混合在一起LOCK
.
无锁算法试图避免的高级锁可以保护执行可能需要任意时间的任意代码片段,因此,这些锁必须将线程置于等待状态,直到锁可用,这是一项代价高昂的操作,例如暗示维护等待线程的队列.
这与CPU LOCK
前缀功能完全不同,后者仅保护单个指令,因此可能仅在该单个指令的持续时间内保留其他线程.由于这是由CPU本身实现的,因此不需要额外的软件工作.
因此,开发无锁算法的挑战并不是完全消除同步,它归结为将代码的关键部分减少到由CPU本身提供的单个原子操作.
@Peter Cordes:OP的实际问题在[本评论]中显而易见(/sf/ask/17360801/?noredirect=1#comment44084729_27837731).在OP承认高级锁和指令前缀之间的混淆是实际问题后,我才发布了答案.您的添加对于将来的读者在搜索"锁定前缀"后找到此问题仍然有价值.
@Rohit Sachan:您可以说它拥有BUS锁,但是由于它对每个内存访问都有效,所以唯一的区别在于,它是为一条指令进行的两次内存访问而持有的,更重要的是,它在交谈时只会造成混乱关于“无锁编程”。换句话说,您应该始终关心讨论是关于硬件还是软件体系结构……
我认为OP部分地问"没有'锁定'的'cmpxchg`有什么意义?".请参阅[我的回答](/sf/ask/17360801/#44273130):英特尔以这种方式设计它,因为它在单处理器系统上很有用.