pthreads和SSE弱内存排序问题

9

Linux的glibc pthread函数在x86_64上是否作为弱序内存访问的栅栏呢?(我感兴趣的确切函数是pthread_mutex_lock/unlock)。

SSE2提供了一些具有弱内存排序的指令(特别是非临时存储,如movntps)。如果您使用这些指令并希望保证另一个线程/核心看到顺序,则需要显式地进行栅栏操作,例如sfence指令。

通常情况下,您期望pthread API适当地作为栅栏。但是,我怀疑x86上的普通C代码不会生成弱序内存访问,因此我不确定pthread是否需要作为弱序访问的栅栏。

通过阅读glibc pthread源代码,mutex最终是使用“lock cmpxchgl”实现的,至少在未竞争的路径上是如此。所以我猜想我需要知道的是该指令是否对SSE2的弱序访问起到了栅栏的作用?


好的,没有人回答,所以我卷起袖子写了一个测试程序。目前为止的进展:
  • 使用pthread自旋锁,我可以轻松地证明它们不是栅栏。
  • 我未能产生pthread互斥锁不作为栅栏的情况。

我不确定失败是因为互斥锁是栅栏还是我只是幸运。我的测试代码在https://gist.github.com/rcls/c855e3e782253e58e046
- user1998586
1个回答

4
非时间相关存储需要使用 sfence 指令进行正确排序。
然而,实现简单互斥锁的有效用户级别假设是通过简单写入释放锁定,不涉及写缓冲区刷新,与原子读-修改-写操作(如 lock cmpxchg)相反,后者涉及完整的内存屏障。
因此,当 unlock 没有应用于非时间相关存储的 store-with-release 语义的效果时,就会出现这种情况。 因此,这些 SSE 存储可以在解锁之后和另一个线程获取互斥锁之后重新排序。

谢谢,我只考虑了锁操作,忽略了在弱序存储之后解锁的排序语义是至关重要的。 - user1998586
重新阅读glibc源代码,这与我的测试结果一致。 pthread_mutex_unlock似乎作为一个障碍使用了锁定指令(通过lowlevellock)。 pthread_spin_unlock使用普通存储。 [尽管其他差异在于pthread_spin_unlock更快 - 大概任何足够缓慢的操作在实践中都会在这里作为一个障碍,即使架构描述没有保证。] - user1998586

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接