2015-01-08 2 views
6

корпорации Intel документация наЯвляется x86 CMPXCHG атомом?

http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf

говорит

«Эта команда может быть использована с префиксом LOCK, чтобы команда должна быть выполнена атомарно.»

Мой вопрос

  1. Может CMPXCHG работать с адресом памяти? Из документа, похоже, нет, но может ли кто-нибудь подтвердить, что работает только с фактическим VALUE в регистре, а не с адресом памяти?

  2. Если CMPXCHG не является атомарным и уровень высокого уровня CAS должен быть реализован через LOCK CMPXCHG (с префиксом LOCK), какова цель введения такой инструкции вообще?

    Префикс
+0

Очевидно, вы можете использовать адрес памяти, вот и все. Первый операнд имеет тип r/m, так что вы идете. И как вы могли бы префикс инструкции с помощью 'lock', если бы она сама не существовала? – harold

+0

@harold Я не совсем понимаю, чего не существует. Вы префикс LOCK, если вы хотите, чтобы команда была атомарной. Итак, CMPXCHG, без префикса LOCK, является атомарным или нет? –

+0

Нет, но в вашем вопросе 2 вы, кажется, спрашиваете, почему существует «cmpxchg без блокировки», что является нечетным, поскольку комбинация не может существовать без частей - если это не то, что вы имели в виду, тогда вы можете уточнить? – harold

ответ

9

Вы смешиваете высокоуровневые замки с низкоуровневой функцией CPU, которая, как оказалось, называется LOCK.

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

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

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

+0

Тогда правильно ли сказать, что CMPXCHG по-прежнему удерживает блокировку, которая отличается от блокировки уровня программы (например, блокировка JVM) –

+1

@Rohit Sachan: вы можете сказать, что она держится блокировка BUS, но поскольку это имеет место для каждого доступа к памяти, единственное различие заключается в том, что оно удерживается для двух обращений к памяти, сделанных одной инструкцией, и, что более важно, это просто запутывает, когда речь идет о «программировании с блокировкой». Другими словами, вы всегда должны заботиться о том, обсуждается ли речь об аппаратной или программной архитектуре ... – Holger

+2

Я думаю, что OP отчасти спрашивает: «В чем смысл' cmpxchg' без 'lock'?». См. [Мой ответ] (https://stackoverflow.com/questions/27837731/is-x86-cmpxchg-atomic/44273130#44273130): Intel разработала его таким образом, потому что он полезен в однопроцессорной системе. –

2

Замок для блокировки доступа к памяти для текущей команды, так что другие команды, которые находятся в трубопроводе CPU может получить доступ к памяти в данный момент. Используя префикс LOCK, выполнение команды не прерывается другой командой в конвейере CPU из-за доступа к памяти других команд, которые выполняются одновременно. Руководство INTEL говорит:

Приставка ЗАМОК может предваряться только к следующему в построениями и только к тем формам инструкций, где адресат операнд операнд памяти: ADD, ADC, и, BTC , BTR, BTS, CMPXCHG, CMPXCH8B, CMPXCHG16B, DEC, INC, NEG, NOT, OR, SBB, SUB, XOR, XADD и XCHG. Если префикс LOCK используется с одной из этих инструкций и , операнд источника является операндом памяти, может быть сгенерировано неопределенное исключение кода операции (#UD).

6

Похоже, часть того, что вы на самом деле спрашиваете:

Почему не lock префикса неявного для cmpxchg с операндом памяти, like it is for xchg?

Простой ответ (что другие дали) - это просто, что Intel разработала его таким образом. Но это приводит к вопросу:

Почему Intel это сделала? Есть ли прецедент для cmpxchg без lock?

На однопроцессорной системе, cmpxchgявляется атомных по отношению к другим потокам, или любой другой код, работающий на одном ядре процессора. (Но не для «системных» наблюдателей, таких как устройство ввода-вывода с памятью или устройство, которое DMA считывает нормальную память, поэтому lock cmpxchg имеет значение даже для однопроцессорных схем процессора).

Контекстные коммутаторы могут выполняться только на прерываниях, а прерывания происходят до или после инструкции, а не в середине. Любой код, запущенный на том же CPU, будет видеть, что cmpxchg либо полностью выполнен, либо вообще нет.


Например, ядро ​​Linux обычно компилируется с поддержкой SMP, поэтому он использует lock cmpxchg для атомной CAS. Но при загрузке в однопроцессорной системе он исправляет префикс lock до nop везде, где этот код был встроен, поскольку nopcmpxchg работает намного быстрее, чем lock cmpxchg. Для получения дополнительной информации см. Это LWN article about Linux's "SMP alternatives" system. Он может даже заплатить до lock префиксов перед подключением второго процессора.

Подробнее о атомарностью отдельных инструкций по однопроцессорных систем in this answer, и в @supercat's answer + comments на Can num++ атомарные для int num. См. my answer there для получения подробной информации о том, как атомичность действительно работает/реализована для инструкций read-modify-write, таких как lock cmpxchg.


(Это же рассуждение относится и к cmpxchg8b/cmpxchg16b и xadd, который обычно используется только для Synchonization/атомных опсов, а не делать однопоточные коды работать быстрее. Очевидно, что память назначение add [mem], reg полезен вне lock add [mem], reg кейс.)

+0

«Но при загрузке в однопроцессорной системе исправление префикса блокировки будет выполняться везде, где этот код был встроен, поскольку nop cmpxchg работает намного быстрее, чем блокировка cmpxchg». Предположим, вы имеете в виду компиляцию в однопроцессорной системе? Поскольку я не знаю, что ОС может исправлять такие скомпилированные инструкции во время выполнения. –

+0

@AlexSuo: Нет, система Linux [SMP alternatives] (https://lwn.net/Articles/164121/) действительно исправляет образ ядра в системах UP. (И BTW, если бы это была просто компиляция, это зависело бы от того, строили ли вы * систему * UP, а не * на * системе UP.Я думаю, что если вы не укажете 'CONFIG_SMP', некоторые блокировки/материал синхронизации может быть полностью исключен, а не зашифрован в NOP во время загрузки. Но в наши дни, вероятно, это не так много, особенно со стандартным 'CONFIG_PREEMPT', который позволяет убрать код ядра. –

Смежные вопросы