В WB-памяти a = b = 0
P1:
a = 1
SFENCE
b = 1P2:
WHILE (b == 0) {}
LFENCE
ASSERT (a == 0)
Я понимаю, что ни SFENCE
, ни LFENCE
.
А именно, поскольку для этого типа памяти x86 обеспечивает:
- Считывание не может быть переупорядочено с помощью более старых чтений
- Магазины не могут быть переупорядочены со старыми хранилищами.
- Магазины транзитивно видны
Инструкции asm
lfence
иsfence
не допускаются, если вы не используете хранилища NT (или NT загружается из памяти WC, например, видеопамяти). (На самом деле,movntdqa
загрузки могут быть заказаны толькоmfence
на бумаге , а неlfence
. В этом случае Я не знаю, когда вы когда-нибудь использовалиlfence
. Он был добавлен в ISA вместе сsfence
+mfence
одновременно с хранилищами NT, доmovntdqa
, возможно, просто для полноты / на случай, если это когда-либо понадобилось.)Иногда возникает путаница вокруг этой точки, потому что внутренняя часть C / C ++ для
lfence
иsfence
также являются барьерами компилятора. Это необходимо в C / C ++, но его можно получить дешевле с помощью GNU Casm("":::"memory");
или (чтобы упорядочить операцииatomic
1 )std::atomic_signal_fence(std::memory_order_acq_rel)
. Ограничивает переупорядочение времени компиляции , не заставляя компилятор выдавать любые бесполезные инструкции asm-барьера.Переупорядочение во время выполнения уже заблокировано моделью памяти x86, за исключением переупорядочения StoreLoad, для которого требуется
mfence
.lfence
+sfence
не суммировать сmfence
. См. Имеет ли смысл инструкция LFENCE для процессоров x86 / x86_64? и другие различные SO Q & Как насчет этих инструкций.Вот почему
std::atomic_thread_fence(std::memory_order_acq_rel)
также компилирует нулевые инструкции на x86, но с барьерами на слабо упорядоченных архитектурах.lfence
также является инструкцией сериализации на микроархитектурах Intel (но, возможно, нет AMD?). Это было все время, но Intel недавно сделала эту гарантию официальной, чтобы методы смягчения воздействия Spectre могли безопасно использовать ее вместо гораздо более неудобногоcpuid
.atomic_signal_fence
в gcc также может быть барьером компилятора для простых неatomic
переменных; это был последний раз, когда я проверял с помощью gcc (в то время какatomic_thread_fence
этого не было), но это, вероятно, просто деталь реализации, когда не задействованы переменныеatomic
. Когда есть переменныеatomic
, компилятор знает, что эти переменные могут обеспечивать порядок, позволяющий другим потокам обращаться к неатомарным переменным без UB, поэтому порядок необходим.