给定此伪代码,全局存在一个原子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) ...
}

不理会虚假唤醒的可能性; 我们可以从上面的代码中推断出XY同步吗? 基本上,它可以归结为futex本身是否旨在在唤醒的等待中实现获取/释放语义。

有一点上下文:TSAN无法理解futex系统调用(例如,参见herehere)。

现在,通常,当使用futex来实现互斥量,信号量或其他某种同步原语时,它还具有一个原子变量,该原子变量通过“锁定”侧装入获取顺序,并通过“解锁”存储在释放顺序中边。 (以上,我故意使用宽松的语义。)

获取/释放足以实现同步,在形式上是正确的,并且被TSAN识别(对于以这种方式实现的锁,它不报告任何内容,例如Qt中的QBasicMutex)。

这个问题主要是关于论坛帖子linked above中提供的关于使用获取/释放语义来标记futex操作本身的建议。 这样的标记正确吗?

(我知道C++抽象机对futex一无所知。它甚至对pthreads也一无所知,但是TSAN知道。对于在pthread_create之前发生的代码也在在新创建的线程中运行的代码之前也发生了。换句话说,这不是语言律师的问题...)

最佳答案

man futex(2) :



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



换句话说,futex syscall在内核中的作用等同于C++ 11:

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

09-27 08:41