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