последовательно согласованная атомная нагрузка на x86 - PullRequest
2 голосов
/ 11 февраля 2011

Меня интересует последовательная согласованная операция загрузки на x86. Насколько я вижу из списка ассемблера, сгенерированного компилятором, он реализован как обычная загрузка на x86, однако обычные загрузки, насколько я знаю, гарантированно приобретают семантику, в то время как обычные хранилища гарантированно имеют освобождение. Последовательное согласованное хранилище реализовано в виде заблокированного xchg, а загрузка - в виде простой загрузки. Это звучит странно для меня, не могли бы вы объяснить это подробнее?

добавлены

Только что обнаружил в интернете, что последовательная согласованная атомарная загрузка может быть выполнена простым перемещением, пока хранение выполняется с заблокированным xchg, но не было никаких доказательств и ссылок на документацию. Вы знаете, где я могу прочитать об этом?

Заранее спасибо.

Ответы [ 3 ]

8 голосов
/ 27 июня 2011

Обычного MOV на x86 достаточно для атомарно-последовательной последовательной нагрузки, пока хранилища SC выполняются с помощью LOCK редактированных инструкций, значение выровнено правильно и используется «нормальный» режим кэширования WB.

См. Мое сообщение в блоге по адресу http://www.justsoftwaresolutions.co.uk/threading/intel-memory-ordering-and-c++-memory-model.html для полного сопоставления и документацию по процессорам Intel по адресу http://developer.intel.com/products/processor/manuals/index.htm для получения подробной информации о разрешенных заказах.

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

1 голос
/ 17 февраля 2011

Чтения на x86 по своей природе являются атомарными, если они выровнены, в разделе под инструкцией MOV в руководствах по сборке Intel vol 2A следует упомянуть это, также как и с префиксом LOCK. Другие тома могут также упомянуть об этом

однако, если вы хотите atomic read, вы можете использовать _InterlockedExchangeAdd((LONG*)&var,0) aka LOCK XADD, это приведет к старому значению, но не изменит его значение, то же самое можно сделать с InterlockCompareExchange((LONG*)&var,var,var) aka LOCK CMPXCHG, но ИМО, в этом нет необходимости

1 голос
/ 16 февраля 2011

Регистрация в памяти передачи и наоборот, насколько я знаю, не атомарны в многопроцессорной среде.

READING

XOR EAX, EAX
LOCK XADD [address], EAX

Эта первая инструкция обнулитсярегистр EAX, вторая инструкция будет обмениваться содержимым обоих EAX с [адресом] и снова будет хранить сумму обоих в [адрес].Поскольку ранее регистр EAX был нулевым, ничего не изменилось.

WRITING

XCHG [address], EAX

Регистр EAX получит значение для сохранения по указанному адресу.

РЕДАКТИРОВАТЬ : LOCK ADD EAX, [адрес] вызовет «Исключение недопустимого кода операции», поскольку операндом назначения не является адрес памяти.

Сгенерировано исключение недопустимого кода (#UD)когда префикс LOCK используется с любой другой инструкцией или когда в память не выполняется операция записи. 8.1.2.2 Программно-управляемая блокировка шины

...