Sys*_*Fun 1 c assembly atomic atomicity
addl, $9, _x(%rip)
Run Code Online (Sandbox Code Playgroud)
_x是一个全局变量.基本上我不确定在这种情况下如何实现添加到全局变量以及在多处理器系统中是否存在与此线路相关的固有竞争条件.
正如duskwuff指出的那样,你需要一个lock前缀.
原因是:
addl $9,_x(%rip)
Run Code Online (Sandbox Code Playgroud)
从记忆系统的角度来看,实际上是三个"微操作"[这里%eax只是为了说明 - 从未真正使用过]:
mov _x(%rip),%eax
addl $9,%eax
mov %eax,_x(%rip)
Run Code Online (Sandbox Code Playgroud)
这是一个有效的事件序列.这由lock前缀保证.最后,_x 将是18:
# this is a valid sequence
# cpu 1 # cpu 2
mov _x(%rip),%eax
addl $9,%eax
mov %eax,_x(%rip)
mov _x(%rip),%eax
addl $9,%eax
mov %eax,_x(%rip)
Run Code Online (Sandbox Code Playgroud)
但是,如果没有lock,我们可以得到:
# this is an invalid sequence
# cpu 1 # cpu 2
mov _x(%rip),%eax
mov _x(%rip),%eax
addl $9,%eax addl $9,%eax
mov %eax,_x(%rip)
mov %eax,_x(%rip)
Run Code Online (Sandbox Code Playgroud)
在结束时,_x将是9,一种序列的进一步混杂可能产生18.所以,根据在两个CPU的微OPS之间的准确的测序,我们可以有任一 9或18.
我们可以让它变得更糟.如果CPU 2添加8而不是9,则序列不会 lock产生任何:8,9或17
更新:
根据一些评论,只是为了澄清术语.
当我说微操作时......它是引号,所以我在创造一个术语以供本文讨论.它并不意味着直接转换为x86处理器文献中定义的x86 uops.我本可以[也许应该 ]说出步骤.
同样,尽管使用x86 asm表达步骤似乎最容易和最清楚,但我可能更抽象:
(1) FETCH_MEM_TO_MREG _x
(2) ADD_TO_MREG 9
(3) STORE_MREG_TO_MEM _x
Run Code Online (Sandbox Code Playgroud)
不幸的是,这些步骤纯粹是在硬件逻辑中执行的(即程序无法通过调试器查看它们或逐步执行它们).存储器系统(例如,高速缓存逻辑,DRAM控制器等)将注意到(并且必须响应)步骤(1)和(3).CPU的ALU将执行步骤(2),这对于存储器逻辑是不可见的.
请注意,某些RISC CPU拱门没有可用于内存的添加指令,也没有锁定前缀.见下文.
除了阅读一些文献之外,检查效果的一种实用方法是创建一个使用多个线程(via pthreads)并使用一些C原子操作和/或的C程序pthread_mutex_lock.
此外,这个页面以原子方式递增两个整数,CAS给出了一个答案,还有一个链接到另一个人在cppcon给出的视频讲话(关于"无锁"实现)
在这个更通用的模型中,它还可以说明在没有正确记录锁定的数据库中会发生什么.
实现方式的实际机制lock可以是特定于x86模型的.
并且,可能,特定于目标指令(例如,lock如果目标指令是[比较] addlvs,则工作方式不同xchg),因为处理器可能能够使用更有效/特殊类型的存储器周期(例如像原子"读取 - 修改 - 写入" ").
在其他情况下(例如,对于单个周期数据太宽或跨越缓存行边界),它可能必须锁定整个内存总线(例如,获取全局锁并强制完全序列化),执行多次读取,进行更改,执行多次写入,然后解锁内存总线.此模式类似于将内容包装在互斥锁定/解锁配对内的方式,仅在内存总线逻辑级别的硬件中完成
关于ARM [RISC cpu]的注释.ARM只支持ldr r1,memory_address,str r1,memory_address但不是 add r1,memory_address.它只允许add r1,r2,r3[即它是"三元"]或可能add r1,r2,#immed.为了实现锁定,ARM有两个特别说明:ldrex和strex那必须进行配对.在上面的抽象模型中,它看起来像:
ldrex r1,_x
add r1,r1,#9
strex r1,_x
// must be tested for success and loop back if failed ...
Run Code Online (Sandbox Code Playgroud)