Достигает ли пара ожидания/пробуждения фьютекса семантики получения/освобождения?

Учитывая этот псевдокод, где глобально атомарное целое 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, также происходит до кода, работающего во вновь созданном потоке. Другими словами, это не вопрос языкового юриста...)


person peppe    schedule 17.05.2019    source источник


Ответы (1)


Из man futex(2):

Загрузка значения слова фьютекса, сравнение этого значения с ожидаемым значением и фактическая блокировка будут происходить атомарно и будут полностью упорядочены по отношению к параллельным операциям, выполняемым другими потоками над тем же словом фьютекса. strong> Таким образом, слово фьютекса используется для связи синхронизации в пользовательском пространстве с реализацией блокировки ядром. По аналогии с атомарной операцией сравнения-и-обмена, которая потенциально изменяет разделяемую память, блокировка через фьютекс является атомарной операцией сравнения-и-блокировки.

Этот общий порядок соответствует C++ std::memory_order_seq_cst:

Операция загрузки с этим порядком памяти выполняет операцию получения, сохранение выполняет операцию освобождения, а чтение-модификация-запись выполняет как операцию получения, так и операцию освобождения, плюс существует единый общий порядок, в котором все потоки наблюдают все изменения в том же порядке.

Другими словами, futex syscall выполняет в ядре эквивалент C++11:

a.compare_exchange_strong(..., std::memory_order_seq_cst, std::memory_order_seq_cst);
person Maxim Egorushkin    schedule 17.05.2019
comment
Должно быть, я перечитал man 2 futex раз десять и почему-то так и не понял этого предложения. Спасибо! - person peppe; 18.05.2019
comment
Что гарантирует, что реализация фьютекса в ядре совместима с реализацией std::memory_order_seq_cst конкретным компилятором? - person curiousguy; 29.05.2019
comment
Хотя это также то, что я интерпретировал, когда читал документацию фьютекса, я все еще не совсем убежден ... Чтобы получить определенный ответ, вероятно, следует посмотреть на полученный код сборки ядра фьютекса и сравнить его с кодом. compare_exchange_strong с упомянутым вами memory_order_seq_cst (например, на ARM). Интересно, можно ли это сделать на Godbolt? - person Carlo Wood; 23.09.2019
comment
В нем говорится, что «существует единый общий порядок, в котором все потоки наблюдают за всеми модификациями в одном и том же порядке ‹местоположения памяти фьютекса›». Последовательная согласованность будет означать, что существует единый общий порядок, в котором все потоки наблюдают за всеми изменениями ЛЮБОЙ атомарной переменной (которая также использует seq-cst). Я считаю, что для операций RMW этот общий порядок всегда существует для области памяти, которую модифицирует RMW. - person Carlo Wood; 24.09.2019
comment
@CarloWood В текущих атомарных инструкциях RMW для x86 есть единый общий порядок. - person Maxim Egorushkin; 24.09.2019