Учитывая этот псевдокод, где глобально атомный 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
синхронизируется с Y
? По сути, это сводится к тому, предназначен ли сам futex для достижения семантики получения / выпуска через ожидание, которое пробуждается. .
Немного контекста: TSAN не понимает системный вызов futex (например, см. здесь , здесь ).
Теперь, обычно, при использовании futex для реализации мьютекса, семафора или какого-либо другого примитива синхронизации, у одного также есть атомарная переменная, которая загружается с порядком получения со стороны «блокировки», и хранится в порядке релиза стороной «разблокировки». (Выше я намеренно использую расслабленную семантику.)
Этого приобретения / освобождения достаточно для достижения синхронизации, формально правильно, и он распознается TSAN (который ничего не сообщает о блокировках, реализованных таким образом, например, QBasicMutex в Qt).
Этот вопрос в основном касается предложения, предложенного в сообщении на форуме , связанного выше , для обозначения операций futex самих с семантикой получения / выпуска. Будет ли такая пометка правильной?
(Я знаю, что абстрактная машина C ++ ничего не знает о futex
. Она даже ничего не знает о pthreads, но TSAN знает, и знает, что, например, код, который происходит до pthread_create
, также происходит до кода работает в новой ветке создания. Другими словами, это не вопрос языкового адвоката ...)