В действительно сильной модели памяти испускание инструкций забора было бы ненужным. Все обращения к памяти будут выполняться по порядку, и все хранилища будут видны глобально.
Необходимы заборы памяти, потому что современные распространенные архитектуры не обеспечивают надежную модель памяти - x86 / x64 может, например, изменить порядок чтения относительно записи. (Более подробный источник - "Руководство разработчика программного обеспечения для архитектуры Intel® 64 и IA-32 , 8.2.2 Упорядочение памяти в P6 и более поздних семействах процессоров" ). Как пример из gazillions, алгоритм Деккера потерпит неудачу на x86 / x64 без заборов.
Даже если JIT создает машинный код, в котором аккуратно размещаются инструкции с загрузками и хранилищами памяти, его усилия бесполезны, если ЦП затем переупорядочивает эти нагрузки и сохраняет - что он может, пока сохраняется иллюзия последовательной согласованности для текущего контекста / потока.
Рискованное упрощение: оно может помочь визуализировать нагрузки и хранилища, являющиеся результатом потока инструкций, в виде гремящего стада диких животных.
Когда они пересекают узкий мост (ваш процессор), вы никогда не можете быть уверены в порядке животных, так как некоторые из них будут медленнее, некоторые быстрее, некоторые обгоняют, некоторые отстают.
Если в начале, когда вы генерируете машинный код, вы разделяете их на группы, помещая между ними бесконечно длинные ограждения, вы, по крайней мере, можете быть уверены, что группа A предшествует группе B.
Заборы обеспечивают порядок чтения и записи. Формулировка не точная, но:
- Ограждение магазина «ожидает» завершения всех ожидающих операций хранения (записи), но не влияет на загрузку.
- ограничитель загрузки «ждет» завершения всех ожидающих операций загрузки (чтения), но не влияет на хранилища.
- полный забор "ждет" всех операций хранения и загрузки до конца. Это имеет эффект, который читает и пишет до того, как забор будет выполнен до того, как записи и загрузки будут на «другой стороне забора» (приходят позже, чем забор).
То, что JIT испускает для полного ограждения, зависит от архитектуры (CPU) и того, какой порядок памяти гарантирует это.
Поскольку JIT точно знает, на какой архитектуре он работает, он может выдавать правильные инструкции.
На моем компьютере x64 с .NET 4.0 RC это lock or
.
int a = 0;
00000000 sub rsp,28h
Thread.MemoryBarrier();
00000004 lock or dword ptr [rsp],0
Console.WriteLine(a);
00000009 mov ecx,1
0000000e call FFFFFFFFEFB45AB0
00000013 nop
00000014 add rsp,28h
00000018 ret
Руководство разработчика программного обеспечения для архитектур Intel® 64 и IA-32 Глава 8.1.2:
"... заблокированные операции сериализуют все незавершенные операции загрузки и сохранения (то есть ожидают их завершения)."
... "Заблокированные операции являются атомарными по отношению ко всем другим операциям памяти и всем
внешне видимые события. Только выборка инструкций и доступ к таблице страниц могут пройти
заблокированные инструкции. Заблокированные инструкции могут быть использованы для синхронизации данных, записанных
один процессор и считывается другим процессором. "
инструкции по размещению памяти инструкции направлены на решение этой конкретной задачи. MFENCE
можно было бы использовать в качестве полного барьера в приведенном выше случае (по крайней мере, теоретически - для одной операции заблокированные операции могут быть быстрее , для двух это может привести к другому поведению ) , MFENCE
и его друзей можно найти в Глава 8.2.5 «Усиление или ослабление модели упорядочения памяти» .
Есть еще несколько способов сериализации хранилищ и загрузок, хотя они либо нецелесообразны, либо медленнее, чем указанные выше методы:
В главе 8.3 вы можете найти полные инструкции по сериализации , такие как CPUID
. Они также сериализуют поток команд: "Ничто не может передать команду сериализации и
инструкция сериализации не может передавать никакую другую инструкцию (чтение, запись, инструкция
fetch или I / O) ".
Если вы установите память как сильную некэшированную (UC), это даст вам сильную модель памяти : никакие спекулятивные или неупорядоченные обращения не будут разрешены, и все обращения появятся на шине поэтому нет необходимости издавать инструкцию. :) Конечно, это будет немного медленнее, чем обычно.
...
Так что это зависит от. Если бы существовал компьютер с сильными гарантиями заказа, JIT, вероятно, ничего бы не испустил.
IA64 и другие архитектуры имеют свои собственные модели памяти - и, таким образом, гарантии упорядочения памяти (или их отсутствия) - и свои собственные инструкции / способы обращения с памятью / упорядочением загрузки.