futex wait/wake 对是否实现了 acquire/release 语义?

Does a futex wait/wake pair achieve acquire/release semantics?

鉴于此伪代码,其中全局有一个原子 int a 初始化为 0:

线程 1:

// ... some code here (X) ...
a.store(1, relaxed);
futex_wake(&a);

线程 2:

if (futex_wait(&a, 1) == woken_up) {
  assert(a.load(relaxed) == 1);
  // ... some code here (Y) ...
}

忽略虚假唤醒的可能性; 我们可以从上面的代码中推导出X synchronizes-with Y吗? 基本上归结为futex本身是否为了实现acquire/release 等待被唤醒的语义。


一些上下文:TSAN 不理解 futex 系统调用(例如参见 [​​=19=])。

现在,通常情况下,当使用 futex 来实现互斥量、信号量或其他一些同步原语时, 有一个原子变量,它通过获取顺序加载"locking"端,存储在"unlocking"端的release ordering中。 (以上,我故意使用宽松的语义。)

acquire/release 足以实现同步,形式上是正确的, 它被 TSAN 识别(它不会报告任何以这种方式实现的锁,例如 QBasicMutex在 Qt 中)。

这个问题主要是关于论坛 post linked above 中提出的用 acquire/release 语义标记 futex 操作 自身 的建议。 这样的标记是否正确?

(我知道 C++ 抽象机对 futex 一无所知。它甚至对 pthreads 一无所知,但 TSAN 知道,并且知道例如 [=18= 之前发生的代码] 也发生在新建线程中的代码运行之前。也就是说,这不是语言律师问题...)

来自man futex(2)

The loading of the futex word's value, the comparison of that value with the expected value, and the actual blocking will happen atomically and will be totally ordered with respect to concurrent operations performed by other threads on the same futex word. Thus, the futex word is used to connect the synchronization in user space with the implementation of blocking by the kernel. Analogously to an atomic compare-and-exchange operation that potentially changes shared memory, blocking via a futex is an atomic compare-and-block operation.

总排序对应C++ std::memory_order_seq_cst:

A load operation with this memory order performs an acquire operation, a store performs a release operation, and read-modify-write performs both an acquire operation and a release operation, plus a single total order exists in which all threads observe all modifications in the same order.

换句话说,futex 系统调用在内核中相当于 C++11:

a.compare_exchange_strong(..., std::memory_order_seq_cst, std::memory_order_seq_cst);