确定使用障碍物(围栏)的位置 [英] Determining the location for the usage of barriers (fences)

查看:21
本文介绍了确定使用障碍物(围栏)的位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

x86 指令 lfence/sfence/mfence 用于在 Linux 内核中实现 rmb()/wmb()/mb() 机制.很容易理解这些用于序列化内存访问.然而,在编写代码时——在遇到运行时行为中的错误之前,确定何时何地使用它们要困难得多.

The x86 instructions lfence/sfence/mfence are used to implement the rmb()/wmb()/mb() mechanisms in the Linux kernel. It is easy to understand that these are used to serialize the memory accesses. However, it is much more difficult to determine when and where to use these while writing the code -- before encountering the bug in the runtime behavior.

我很想知道在编写/审查代码时是否有可以检查的已知警告,这可以帮助我们确定必须插入障碍的位置.我知道这太复杂了,但是否有经验法则或清单可以帮助我们确定需要这些代码的地方?

I was interested to know if there are known caveats that could be checked, while writing/reviewing the code, that can help us determine where the barriers must be inserted. I understand this is a too complex, but is there a rule-of-thumb or a checklist that can help us identify the code-places where these are needed?

推荐答案

我的经验(不在 Linux 内核中)是两种模式涵盖了绝大多数的防护需求.

My experience (not in the Linux kernel) is that two patterns cover the vast majority of the need for fencing.

模式发送/接收":线程 1 向线程 2 发送数据,并且有一个内存位置以某种方式指示数据已准备好".线程 1 至少需要在数据存储和数据准备好"存储之间建立一个屏障.线程 2 需要在表示数据已准备好"的数据加载和数据加载之间设置一道屏障.

Pattern "Send/receive": Thread 1 sends data to thread 2, and there is a memory location that somehow indicates "data is ready". Thread 1 needs at least an sfence between the store of the data and the store into "data is ready". Thread 2 needs an lfence between the load of the data that says "data is ready" and the load of the data.

如果传输中只涉及常规(非临时、DMA 设备等)加载/存储,则只需要编译器围栏.此外,以 LOCK 为前缀的指令意味着栅栏.例如,有时数据准备好"位置不仅仅是一个标志,而是一个原子计数器,用于操作它的以 LOCK 为前缀的增量/减量可以作为栅栏.

If only regular (NOT non-temporal, DMA devices etc.) load/stores are involved in the transfer, then only compiler fences are necessary. Also, LOCK-prefixed instructions imply fences. For example, sometimes the "data is ready" location is not simply a flag, but an atomic counter, and the LOCK-prefixed increment/decrement used to manipulate it can serve as the fence.

这个模式也涵盖了自旋锁.释放锁是一个发送".获取锁是接收".

This pattern also covers spin locks. Releasing a lock is a "send". Acquiring a lock is " receive.

模式共识":两个线程必须就某事达成共识.必须有一个 mfence(或一个以 LOCK 为前缀的指令隐含的).栅栏必须在我发表了我的投票"和我阅读了其他帖子的投票"之间.Dekker 的协议就是一个例子.困难的部分是发现这种模式.我们曾经错过了一个深入 TBB 内部的共识问题是是否抛出了异常?"最终我们意识到这是一个共识问题,因此需要一个 mfence.

Pattern "Consensus": Two threads have to reach consensus about something. There must be an mfence (or one implied by a LOCK-prefixed instruction). The fence must be between the "I published my vote" and "I read the other thread's vote". Dekker's protocol is an example. The hard part is spotting this pattern. We once missed one deep in the internals of TBB where the consensus problem was "has an exception been thrown?" Eventually we realized that it was a consensus problem and consequently needed an mfence.

以上两种模式是不能涵盖所有情况的经验法则,但我发现它们涵盖了 99% 的情况.

The two patterns above are rules of thumb that do not cover all cases, but I find that they cover 99% of cases.

这篇关于确定使用障碍物(围栏)的位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆