`原子\u比较\u交换\u强\u显式()`--'success'和'failure'参数的各种组合在不相等时做什么?
与原子比较交换弱显式函数一样,原子比较交换强显式函数采用两个内存顺序参数成功和失败。取消选择C11/C18标准,我发现成功和失败的允许值为: 该标准还规定: 此外,如果比较为真,则根据 成功,如果比较是错误的,记忆会根据 失败这些操作是原子读修改写操作5.1.2.4 您的ARM、POWER-PC和其他LL/SC设备执行加载链接/Cmp/存储条件序列以实现原子Cmp交换,其中加载链接可能是或可能不是“获取”,存储条件可能是或可能不是“释放” 所以我可以理解:成功=\u acq\u rel,失败=\u acquire 我无法理解的是:成功=失败=放松。当然,为了实现acq rel,负载链路必须是acquire?如果cmp失败,那么降级到(u)肯定为时已晚了吗 当成功和失败参数的组合不相等时,它们的预期含义是什么`原子\u比较\u交换\u强\u显式()`--'success'和'failure'参数的各种组合在不相等时做什么?,c,assembly,atomic,stdatomic,C,Assembly,Atomic,Stdatomic,与原子比较交换弱显式函数一样,原子比较交换强显式函数采用两个内存顺序参数成功和失败。取消选择C11/C18标准,我发现成功和失败的允许值为: 该标准还规定: 此外,如果比较为真,则根据 成功,如果比较是错误的,记忆会根据 失败这些操作是原子读修改写操作5.1.2.4 您的ARM、POWER-PC和其他LL/SC设备执行加载链接/Cmp/存储条件序列以实现原子Cmp交换,其中加载链接可能是或可能不是“获取”,存储条件可能是或可能不是“释放” 所以我可以理解:成功=\u acq\u rel,失败=\
[总是有可能我被标准迷惑了,事实上,故障内存顺序可能只是成功内存顺序的读取一半。]在某些ISA上的asm中实现获取加载的一种方法是简单加载,然后是围栏,例如,在ARMv8引入ldar/ldaxr之前的PowerPC或ARM等ISA上。如果失败顺序不包括获取,则可以跳过后面的隔离 在伪asm中,如果没有真正的ISA,LL/SC CAS_可能看起来像这样:
ll r0, mem
cmp r0, r1
jne .fail # early-out compare fail
sc r2, mem # let's pretend this sets CF condition code on SC failure
jc .fail # jump if SC failed
lwsync # LoadLoad, StoreStore, and LoadStore but not StoreLoad
... CAS success path
.fail: # we jump here without having executed any barriers
... CAS failure path
我认为这可能是mem的一个有效实现;在某些机器上
这只是一个获取操作,因此整个RMW可以与早期操作重新排序。LL/SC的性质使它们在全局顺序中保持一致。手术前没有障碍,只有手术后
lwsync是一条PowerPC屏障指令,它阻止除StoreLoad之外的所有重新排序,即不刷新存储缓冲区。及
为了在大多数ISA上实现CAS…、acq_rel,我们还将在LL/SC之前运行一个屏障,将其与早期操作分离,创建发布部分。即使在故障路径上也会执行,但不会创建acquire语义。它不会将负载与以后的操作分开
如果比较失败的话,你可能不想把LL和SC之间的界限设置为跳过。这将延长事务的时间,并使它有更多的机会因其他线程的活动而失败
在实际的ASM之上实现C++内存模型时,总是做一些必要的但不强的事情,考虑到底层ISA所提供的原语的限制。大多数ISA不会使CASacq_rel、松弛失效路径实际上像普通松弛载荷一样便宜,因为这是不可能的,或者因为它会损害正常情况下的性能。但在某些情况下,它仍然比失败方需要获取语义的成本更低
一些ISA(如ARM)显然只有完整的dsb ish屏障,因此即使是acq_rel也会耗尽存储缓冲区。因此,ARMV8引入获取负载和顺序释放存储是非常好的,因为它完全匹配C++ +SEQ CST语义,并且可能比屏障便宜得多。 < P>在ASA上实现在某些ISAS中获取负载的一种方法是一个简单的负载,接着是一个围栏,例如,在ARMv8引入ldar/ldaxr之前的PowerPC或ARM等ISA上。如果失败顺序不包括获取,则可以跳过后面的隔离 在伪asm中,如果没有真正的ISA,LL/SC CAS_可能看起来像这样:
ll r0, mem
cmp r0, r1
jne .fail # early-out compare fail
sc r2, mem # let's pretend this sets CF condition code on SC failure
jc .fail # jump if SC failed
lwsync # LoadLoad, StoreStore, and LoadStore but not StoreLoad
... CAS success path
.fail: # we jump here without having executed any barriers
... CAS failure path
我认为这可能是mem的一个有效实现;在某些机器上
这只是一个获取操作,因此整个RMW可以与早期操作重新排序。LL/SC的性质使它们在全局顺序中保持一致。手术前没有障碍,只有手术后
lwsync是一条PowerPC屏障指令,它阻止除StoreLoad之外的所有重新排序,即不刷新存储缓冲区。及
为了在大多数ISA上实现CAS…、acq_rel,我们还将在LL/SC之前运行一个屏障,将其与早期操作分离,创建发布部分。即使在故障路径上也会执行,但不会创建acquire语义。它不会将负载与以后的操作分开
如果比较失败的话,你可能不想把LL和SC之间的界限设置为跳过。这将延长交易时间,并为交易提供更多机会
它可能由于其他线程的活动而失败
在实际的ASM之上实现C++内存模型时,总是做一些必要的但不强的事情,考虑到底层ISA所提供的原语的限制。大多数ISA不会使CASacq_rel、松弛失效路径实际上像普通松弛载荷一样便宜,因为这是不可能的,或者因为它会损害正常情况下的性能。但在某些情况下,它仍然比失败方需要获取语义的成本更低
一些ISA(如ARM)显然只有完整的dsb ish屏障,因此即使是acq_rel也会耗尽存储缓冲区。因此,ARMV8引入获取负载和顺序释放存储是非常好的,因为它完全匹配C++ +SEQ CST语义,并且可能比屏障便宜很多。我现在了解到,对于某些体系结构,读-修改-写的读部分的内存顺序可以在读之后应用。这就解释了失败内存顺序,它不仅仅是成功内存顺序的读取部分,还包括_消耗。[请注意,我还没有遇到一个适用于_consume的体系结构……但那是另一个故事。]消费语义对于几乎每一个在所有读取和自由操作中都不隐含acquire的arch都可能有用。这是很多多CPU系统。但它必须得到编译器的支持,在几乎所有情况下都需要前端到后端的更改。您是否特别困惑于_consume?不再是了。我现在了解到,对于某些体系结构,读-修改-写的读部分的内存顺序可以在读之后应用。这就解释了失败内存顺序,它不仅仅是成功内存顺序的读取部分,还包括_消耗。[请注意,我还没有遇到一个适用于_consume的体系结构……但那是另一个故事。]消费语义对于几乎每一个在所有读取和自由操作中都不隐含acquire的arch都可能有用。这是很多多CPU系统。但它必须得到编译器的支持,在几乎所有情况下都需要前端到后端的更改。