Сравните и поменяйте местами машинный код на C - PullRequest
10 голосов
/ 18 ноября 2010

Как бы вы написали функцию в C, которая выполняет атомарное сравнение и замену целочисленного значения, используя встроенный машинный код (предположим, скажем, архитектуру x86)?Может ли он быть более конкретным, если он написан только для процессора i7?

Перевод выступает в качестве ограничения памяти или он просто обеспечивает порядок упорядочения только в той области памяти, которая включена в сравнение и обмен?Насколько это дорого по сравнению с забором памяти?

Спасибо.

Ответы [ 5 ]

7 голосов
/ 18 ноября 2010

Вы можете использовать инструкцию CMPXCHG с префиксом LOCK для атомарного выполнения.

* 1005 Е.Г. *

lock cmpxchg DWORD PTR [ebx], edx

или

lock cmpxchgl %edx, (%ebx)

Сравнивает значение в регистре EAX со значением по адресу, сохраненному в регистре EBX, и сохраняет значение в регистре EDX в этом месте, если они совпадают, в противном случае загружается значение по адресу, сохраненному в EBX зарегистрироваться в EAX.

Чтобы эта инструкция была доступна, у вас должно быть 486 или более поздняя версия.

7 голосов
/ 18 ноября 2010

Самый простой способ сделать это, вероятно, с помощью встроенного компилятора , например _InterlockedCompareExchange () .Это похоже на функцию, но на самом деле это особый случай в компиляторе, который сводится к одной машинной операции.В случае с MSVC x86, это также работает как ограничение чтения / записи, но это не обязательно верно для других платформ.(Например, на PowerPC вам нужно явно запустить lwsync , чтобы ограничить переупорядочение памяти.)

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

4 голосов
/ 18 ноября 2010

Если ваше целочисленное значение 64-битное, используйте cmpxchg8b 8-байтовое сравнение и обмен в IA32 x86. Переменная должна быть выровнена на 8 байт.

Example:
      mov   eax, OldDataA           //load Old first 32 bits
      mov   edx, OldDataB           //load Old second 32 bits
      mov   ebx, NewDataA           //load first 32 bits
      mov   ecx, NewDataB           //load second 32 bits
      mov   edi, Destination        //load destination pointer
      lock cmpxchg8b qword ptr [edi]
      setz  al                      //if transfer is succesful the al is 1 else 0
3 голосов
/ 15 февраля 2011

Если префикс LOCK пропущен в инструкциях атомарного процессора, атомарная работа в многопроцессорной среде не будет гарантирована .

В многопроцессорной среде сигнал LOCK # гарантирует, чтопроцессор имеет исключительное использование любой совместно используемой памяти, пока подается сигнал. Справочник по набору инструкций Intel

Без префикса LOCK операция не будет прервана никаким событием (прерыванием) только для текущего процессора / ядра.

2 голосов
/ 10 мая 2012

Интересно отметить, что некоторые процессоры не обеспечивают сравнение-обмен, а вместо этого предоставляют некоторые другие инструкции («Загрузить связанные» и «Условное хранилище»), которые можно использовать для синтеза, к сожалению, названного сравнения-и-сравнения.swap (название звучит так, как будто оно должно быть похоже на «сравнение-обмен», но на самом деле его следует называть «сравнить и хранить», поскольку оно выполняет сравнение, сохраняет, если значение совпадает, и указывает, соответствует ли значение и хранилище быловыполнила).Инструкции не могут синтезировать семантику сравнения-обмена (которая предоставляет значение, прочитанное в случае сбоя сравнения), но в некоторых случаях могут избежать проблемы ABA, которая присутствует в Compare-Exchange.Многие алгоритмы описаны в терминах операций «CAS», потому что они могут использоваться в обоих стилях CPU.

Инструкция «Load Linked» говорит процессору прочитать ячейку памяти и посмотреть каким-то образом, чтобы увидеть,это может быть написано.Инструкция «Условное хранилище» дает указание процессору записать ячейку памяти только в том случае, если после последней операции «Load Linked» ничего не могло быть записано.Обратите внимание, что определение может быть пессимистичным;например, обработка прерывания может сделать недействительной последовательность «Load-Linked» / «Conditional Store».Аналогично, в многопроцессорной системе последовательность LL / CS может быть признана недействительной другим ЦП, осуществляющим доступ к местоположению в той же строке кэша, что и отслеживаемое местоположение, даже если фактическое отслеживаемое местоположение не было затронуто.При обычном использовании LL / CS используются очень близко друг к другу, с повторным циклом, так что ошибочные аннулирования могут немного замедлить ход событий, но не вызовут особых проблем.

...