确定使用障碍物(栅栏)的位置
Posted
技术标签:
【中文标题】确定使用障碍物(栅栏)的位置【英文标题】:Determining the location for the usage of barriers (fences) 【发布时间】:2013-12-25 04:00:16 【问题描述】:x86 指令lfence/sfence/mfence 用于在Linux 内核中实现rmb()/wmb()/mb() 机制。很容易理解,这些是用来序列化内存访问的。但是,在编写代码时确定何时何地使用它们要困难得多——在遇到运行时行为中的错误之前。
我很想知道在编写/审查代码时是否有可以检查的已知警告,这可以帮助我们确定必须在哪里插入障碍。我知道这太复杂了,但是是否有经验法则或清单可以帮助我们确定需要这些的代码位置?
【问题讨论】:
内存屏障不序列化CPU上的指令,它们序列化外部 CPU的内存访问。要回答您的问题,有必要粘贴整个documentation。 【参考方案1】:我的经验(不是在 Linux 内核中)是两种模式涵盖了绝大多数的防护需求。
模式“Send/receive”:线程 1 向线程 2 发送数据,并且有一个内存位置以某种方式指示“数据已准备好”。线程 1 至少需要在数据存储和存储到“数据准备就绪”之间有一个 sfence。线程 2 需要在表示“数据准备就绪”的数据负载和数据负载之间建立一个 lfence。
如果传输中只涉及常规(不是非临时、DMA 设备等)加载/存储,则只需要编译器围栏。此外,以 LOCK 为前缀的指令意味着栅栏。例如,有时“数据准备就绪”位置不仅仅是一个标志,而是一个原子计数器,用于操作它的以 LOCK 为前缀的增量/减量可以用作栅栏。
此模式还涵盖自旋锁。释放锁是“发送”。获取锁是“接收”。
模式“共识”:两个线程必须就某事达成共识。必须有一个 mfence(或一个以 LOCK 为前缀的指令所暗示的)。栅栏必须在“我发表了我的投票”和“我阅读了其他线程的投票”之间。 Dekker's protocol 就是一个例子。困难的部分是发现这种模式。我们曾经在 TBB 的内部深处错过了一个共识问题是“是否引发了异常?”最终我们意识到这是一个共识问题,因此需要一个 mfence。
以上两种模式是经验法则,并未涵盖所有情况,但我发现它们涵盖了 99% 的情况。
【讨论】:
以上是关于确定使用障碍物(栅栏)的位置的主要内容,如果未能解决你的问题,请参考以下文章
循环栅栏:CyclicBarrier(司令要求任务) 读书笔记
我想在给定区域的随机位置生成敌人。我不想让我的敌人随机出现在障碍物顶部等任何地方