因此,我偶然发现了 Jeff Preshing 的精彩博客文章,其中介绍了什么是Acquire
CPU障碍Release
以及如何通过一些 CPU障碍实现这些障碍。
我还读过关于某种总顺序的文章,它保证与非一致性后关系SeqCst
一致- 尽管有时由于历史原因它可能与由简单/操作建立的前发生关系相矛盾。Acquire
Release
我的问题是,旧的 GCC 内置函数如何映射到 C++11 (及更高版本) 提出的内存模型?具体来说,如何映射__sync_synchronize()
到 C++11 或更高版本的现代 C/C++?
在 GCC手册中,此调用被简单地描述为完整内存屏障,我认为这是所有四种主要屏障(即LoadLoad
/ LoadStore
/ StoreLoad
/StoreStore
屏障)的组合。但sync_synchronize
相当于std::atomic_thread_fence(memory_order_seq_cst)
?或者,从形式上讲,其中一个比另一个更强(我想这里就是这种情况:通常,SeqCst
隔离应该更强,因为它需要工具链/平台以某种方式即兴执行全局排序,不是吗?),而碰巧大多数 CPU只提供同时满足两者(完整内存屏障__sync_synchronize
,完全顺序排序std::atomic_thread_fence(memory_order_seq_cst)
)的指令,例如 x86和 PowerPC ?mfence
hwsync
__sync_synchronize
和要么std::atomic_thread_fence(memory_order_seq_cst)
在形式上相等,要么在实际上相等(即,从形式上讲它们是不同的,但没有商业化的 CPU 会费心区分两者),从技术上讲,memory_order_relaxed
对同一原子的负载仍然不能依赖于与它同步/创建先发生关系,不是吗?
也就是说,从技术上讲,所有这些断言都可以失败,对吗?
// Experiment 1, using C11 `atomic_thread_fence`: assertion is allowed to fail, right?
// global
static atomic_bool lock = false;
static atomic_bool critical_section = false;
// thread 1
atomic_store_explicit(&critical_section, true, memory_order_relaxed);
atomic_thread_fence(memory_order_seq_cst);
atomic_store_explicit(&lock, true, memory_order_relaxed);
// thread 2
if (atomic_load_explicit(&lock, memory_order_relaxed)) {
// We should really `memory_order_acquire` the `lock`
// or `atomic_thread_fence(memory_order_acquire)` here,
// or this assertion may fail, no?
assert(atomic_load_explicit(&critical_section, memory_order_relaxed));
}
// Experiment 2, using `SeqCst` directly on the atomic store
// global
static atomic_bool lock = false;
static atomic_bool critical_section = false;
// thread 1
atomic_store_explicit(&critical_section, true, memory_order_relaxed);
atomic_store_explicit(&lock, true, memory_order_seq_cst);
// thread 2
if (atomic_load_explicit(&lock, memory_order_relaxed)) {
// Again we should really `memory_order_acquire` the `lock`
// or `atomic_thread_fence(memory_order_acquire)` here,
// or this assertion may fail, no?
assert(atomic_load_explicit(&critical_section, memory_order_relaxed));
}
// Experiment 3, using GCC built-in: assertion is allowed to fail, right?
// global
static atomic_bool lock = false;
static atomic_bool critical_section = false;
// thread 1
atomic_store_explicit(&critical_section, true, memory_order_relaxed);
__sync_synchronize();
atomic_store_explicit(&lock, true, memory_order_relaxed);
// thread 2
if (atomic_load_explicit(&lock, memory_order_relaxed)) {
// we should somehow put a `LoadLoad` memory barrier here,
// or the assert might fail, no?
assert(atomic_load_explicit(&critical_section, memory_order_relaxed));
}
我已经在 RPi 5 上尝试了这些代码片段,但我没有看到断言失败。是的,这并没有正式证明任何事情,但它也没有阐明__sync_synchronize
和之间的区别std::atomic_thread_fence(memory_order_seq_cst)
。