#multithreading #pthreads #atomic #sse #memory-fences
#многопоточность #pthreads #атомарный #sse #заборы памяти
Вопрос:
Действуют ли функции pthread Linux glibc на x86_64 как ограждения для слабо упорядоченных обращений к памяти? (pthread_mutex_lock / unlock — это именно те функции, которые меня интересуют).
SSE2 предоставляет некоторые инструкции со слабым упорядочением памяти (в частности, нестационарные хранилища, такие как movntps). Если вы используете эти инструкции и хотите гарантировать, что другой поток / ядро увидит упорядочение, то я понимаю, что для этого вам нужен явный забор, например, инструкция sfence.
Обычно вы ожидаете, что API pthread будет действовать соответствующим образом. Однако я подозреваю, что обычный код C на x86 не будет генерировать слабо упорядоченные обращения к памяти, поэтому я не уверен, что pthreads должен выступать в качестве ограждения для слабо упорядоченных обращений.
При чтении исходного кода glibc pthread мьютекс в конечном итоге реализуется с использованием «lock cmpxchgl», по крайней мере, на непреднамеренном пути. Итак, я предполагаю, что мне нужно знать, действует ли эта инструкция как ограждение для слабо упорядоченных обращений SSE2?
Комментарии:
1. Ну, никто не ответил, поэтому я засучил рукава и написал тестовую программу. Прогресс на данный момент: —— * С помощью спин-блокировок pthread я могу легко продемонстрировать, что они не являются ограждениями. * Мне не удалось создать мьютексы pthread, не действующие как ограждения. —— Я не уверен, вызван ли сбой тем, что мьютексы являются ограждениями, или потому, что мне просто повезло. Мой тестовый код находится на gist.github.com/rcls/c855e3e782253e58e046
Ответ №1:
Для правильного упорядочения инструкций в нестационарных хранилищах требуется. sfence
Однако эффективная реализация простого мьютекса на уровне пользователя предполагает, что он освобождается простой записью, которая не подразумевает промывку буферов записи, в отличие от атомарных операций чтения-изменения-записи, подобных lock cmpxchg
которым, которые подразумевают полную блокировку памяти.
Итак, у вас возникает ситуация, когда unlock
store-with-release
семантика не влияет на применение к нестационарным хранилищам. Таким образом, эти хранилища SSE могут быть переупорядочены после разблокировки и после того, как другой поток получит мьютекс.
Комментарии:
1. Спасибо, я думал только об операции блокировки и пропустил, что семантика упорядочения разблокировки после слабо упорядоченного хранилища — это то, что имеет решающее значение.
2. И повторное чтение исходного кода glibc, это согласуется с результатами моего тестирования. pthread_mutex_unlock, который, по-видимому, действует как ограждение, использует заблокированную инструкцию (через lowlevellock). pthread_spin_unlock использует обычное хранилище. [Хотя другое отличие заключается в том, что pthread_spin_unlock работает быстрее — предположительно, любые достаточно медленные операции на практике будут здесь препятствием, даже если архитектурное описание этого не гарантирует.]