Так много вопросов и статей / книг типа https://mirrors.edge.kernel.org/pub/linux/kernel/people/paulmck/perfbook/perfbook.2018.12.08a.pdf, статьи Preshing, такие как https://preshing.com/20120710/memory-barriers-are-like-source-control-operations/ и вся серия его статей говорят об упорядочивании в памяти абстрактно, с точки зрения гарантий упорядочения и видимости, обеспечиваемых различными типами барьеров. Мой вопрос в том, как эти барьеры и семантика упорядочения памяти реализованы на микроархитектуре x86 и ARM?
Что касается барьеров между хранилищами, похоже, что на x86 буфер хранилища поддерживает программный порядок хранилищ и фиксирует их в L1D (и, следовательно, делает их глобально видимыми в том же порядке). Если буфер хранилища не упорядочен, т. Е. Не поддерживает их в программном порядке, как реализуется барьер хранилища? он просто «маркирует» буфер хранилища таким образом, что он сохраняет до фиксации барьера в когерентный домен кэша до сохранения после? или барьер памяти действительно очищает буфер хранилища и останавливает все инструкции до завершения очистки? Может ли это быть реализовано обоими способами?
Как предотвратить переупорядочение нагрузки-нагрузки для барьеров нагрузки-нагрузки? Трудно поверить, что x86 выполнит все нагрузки по порядку! Я предполагаю, что нагрузки могут выполняться не по порядку, но фиксируются / удаляются по порядку. Если да, то если ЦП выполняет 2 загрузки в 2 разных места, как одна загрузка гарантирует, что она получила значение, скажем, от T100, а следующая получила его в T100 или после него? Что делать, если первая загрузка отсутствует в кеше и ожидает данных, а вторая загрузка попадает и получает свое значение. Когда загрузка 1 получает свое значение, как она гарантирует, что полученное значение не из нового магазина, в котором загружено значение 2? если нагрузки могут выполняться не по порядку, как обнаруживаются нарушения порядка памяти?
Аналогичным образом, как реализованы барьеры между загрузкой и загрузкой (неявные во всех загрузках для x86) и как реализованы барьеры между загрузкой и загрузкой (например, mfence)? т.е. что делают инструкции dmb ld / st и just dmb на микроархитектуре на ARM, и что каждая загрузка и каждое хранилище, и инструкция mfence делают на микроархитектуре на x86, чтобы обеспечить упорядочение памяти?