Как реализуются атомарные операции на аппаратном уровне?

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

Как я себе это представляю, выполнение инструкции должно

  1. получить значение из памяти
  2. сравнить стоимость
  3. в зависимости от сравнения, возможно, сохранить другое значение в памяти

Что мешает другое ядро от доступа к адресу памяти после того, как первый извлек его, но до того, как он установит новое значение? Управляет ли этим контроллер памяти?

edit: если реализация x86 является секретной, я был бы рад услышать, как любое семейство процессоров реализует ее.

4 ответов


здесь статьи над на software.intel.com на что проливает мало света на блокировки пользовательского уровня:

блокировки пользовательского уровня включают использование атомарных инструкций процессор для атомарного обновления пространства памяти. Атомные инструкции включите использовать префикс замка на инструкции и иметь операнд назначения, назначенный адресу памяти. Следующий инструкции могут работать атомарно с префиксом блокировки на текущем Intel процессоры: добавить, АЦП, и, БТЦ, БТР, БТС, CMPXCHG, CMPXCH8B, декабря, ИНК, Нег, нет, или, СББ, суб, гаммирования, XADD, и xchg. [...] По большинству инструкций префикс блокировки должен использоваться явно, за исключением инструкции xchg где префикс блокировки подразумевается, если инструкция включает память адрес.

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

Итак, что мешает другому ядру получить доступ к адресу памяти? Этот протокол когерентности кэша уже управляет правами доступа для строк кэша. Поэтому, если ядро имеет (временные) исключительные права доступа к строке кэша, никакое другое ядро не может получить доступ к этой строке кэша. Для доступа к этой строке кэша другое ядро должно сначала получить права доступа, и протокол для получения этих прав включает текущего владельца. По сути, протокол когерентности кэша предотвращает доступ других ядер к строке кэша в автоматическом режиме.

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


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


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


протокол когерентности кэша сам по себе недостаточен для реализации атомарных операций. Допустим, вы хотите реализовать атомарный инкремент. Ниже приведены шаги

  1. загрузить значение из кэша в регистр
  2. увеличить значение, загруженное в регистр
  3. сохраните обновленное значение обратно в кэш

Итак, чтобы реализовать вышеуказанные 3 Инструкции атомарным способом, мы должны сначала получить эксклюзив доступ к cacheline, который содержит требуемое значение. Как только мы получим эксклюзивный доступ, мы не должны отказываться от эксклюзивного доступа к этому cacheline до завершения операции "store". Это означает, что ЦП, выполняющий атомарные инструкции, не должен отвечать на сообщения протокола когерентности кэша для этой кэш-линии в то же время. Хотя дьявол в деталях, как это реализуется, по крайней мере, дает нам ментальную модель

ниже то, что упомянул Линус Торвальдс об атомных инструкциях

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