内存障碍和在linux上的atomic_t

内存障碍和在linux上的atomic_t,第1张

概述最近我正在阅读一些 Linux内核空间代码,我看到了这一点 uint64_t used;uint64_t blocked;used = atomic64_read(&g_variable->used); //#1barrier(); //#2blocked = atomic64_read(&g_varia 最近我正在阅读一些 Linux内核空间代码,我看到了这一点
uint64_t used;uint64_t blocked;used = atomic64_read(&g_variable->used);       //#1barrIEr();                                     //#2blocked = atomic64_read(&g_variable->blocked); //#3

这段代码片段的语义是什么?确保#1在#3之前执行#2.
可是,我是一个乱七八糟的人,因为这样

#A在64位平台中,将atomic64_read宏扩展为

used = (&g_variable->used)->counter           // where counter is volatile.

在32位平台中,它被转换为使用锁cmpxchg8b.我假设这两个具有相同的语义,对于64位版本,我认为这意味着:

>全部或全部,我们可以排除地址不对齐,字长大于cpu本机字大小的情况.
>无优化,强制cpu从内存位置读取.

atomic64_read没有保留读取顺序的语义!见this

#B屏障宏定义为

/* Optimization barrIEr *//* The "volatile" is due to gcc BUGs */#define barrIEr() __asm__ __volatile__("": : :"memory")

从wiki this起只是防止gcc编译器重新排序读写.

我困惑的是如何禁用cpu的重新排序优化?另外,我可以想到屏障宏是全面的?

解决方法 32位x86处理器不能为64位类型提供简单的原子读取 *** 作.在处理“正常”寄存器的这种cpu上,64位类型上唯一的原子 *** 作是LOCK CMPXCHG8B,这就是为什么在这里使用的.另一种方法是使用MOVQ和MMX / XMM寄存器,但需要了解FPU状态/寄存器,并且要求使用MMX / XMM指令完成对该值的所有 *** 作.

在64位x86_64处理器上,64位类型的对齐读取是原子的,可以使用MOV指令完成,因此只需要一个简单的读取 – 使用volatile只是为了确保编译器实际执行读取,并且不缓存先前的值.

对于读取顺序,您引用的内联汇编程序可确保编译器以正确的顺序发出指令,这是x86 / x86_64 cpu上所需的所有 *** 作,前提是写入顺序正确. x86上的锁定写入有一个完整的顺序;平滑的MOV写入提供了“因果一致性”,所以如果线程A的x = 1然后y = 2,如果线程B读取y == 2,则x的后续读取将看到x == 1.

在IA-64,PowerPC,SPARC和其他具有更宽松内存模型的处理器中,还有更多的是atomic64_read()和barrIEr().

总结

以上是内存溢出为你收集整理的内存障碍和在linux上的atomic_t全部内容,希望文章能够帮你解决内存障碍和在linux上的atomic_t所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/1044360.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-24
下一篇 2022-05-24

发表评论

登录后才能评论

评论列表(0条)

保存