Какая минимальная ассемблера x86, необходимых для взаимоблокировки
Для реализации спин-замка в сборке. Здесь я публикую решение, которое я придумал. Это правильно? Вы знаете более короткий вариант?
Замок:
mov ecx, 0
.loop:
xchg [eax], ecx
cmp ecx, 0
je .loop
Релиз:
lock dec dword [eax]
Eax инициализируется до -1 (что означает, что блокировка свободна). Это должно работать для многих потоков (не обязательно 2).
3 ответа:
Самым коротким, вероятно, будет:
acquire: lock bts [eax],0 jc acquire release: mov [eax],0
Для производительности лучше всего использовать подход" test, test and set " и использовать
pause
, например:acquire: lock bts [eax],0 ;Optimistic first attempt jnc l2 ;Success if acquired l1: pause test [eax],1 jne l1 ;Don't attempt again unless there's a chance lock bts [eax],0 ;Attempt to acquire jc l1 ;Wait again if failed l2: release: mov [eax],0
Для отладки можно добавить дополнительные данные, чтобы облегчить обнаружение проблем, например:
acquire: lock bts [eax],31 ;Optimistic first attempt jnc l2 ;Success if acquired mov ebx,[CPUnumber] lea ebx,[ebx+0x80000000] cmp [eax],ebx ;Is the lock acquired by this CPU? je .bad ; yes, deadlock lock inc dword [eax+4] ;Increase "lock contention counter" l1: pause test [eax],0x80000000 jne l1 ;Don't attempt again unless there's a chance lock bts [eax],31 ;Attempt to acquire jc l1 ;Wait again if failed l2: mov [eax],ebx ;Store CPU number release: mov ebx,[CPUnumber] lea ebx,[ebx+0x80000000] cmp [eax],ebx ;Is lock acquired, and is CPU same? jne .bad ; no, either not acquired or wrong CPU mov [eax],0
Ваш код прекрасен, но если вы ищете высокую производительность, я бы предложил вместо этого:
xor ecx, ecx .loop: lock xchg [eax], ecx test ecx, ecx jz .loop
Причины:
xor ecx, ecx
меньше и не требует литерала,и современные процессоры имеют этот жесткий провод для быстрого регистра нуля.test ecx, ecx
может быть немного меньше и быстрее, чемcmp ecx, 0
, потому что вам не нужно загружать литерал иtest
- это просто побитовая операция, а не вычитание.P.S. Я всегда ставлю туда префикс замка независимо от того, подразумевается ли это, по причинам читаемости - это делает очевидным, что я делаю заблокированную операцию.
Ваш код в порядке, и вы всегда можете попытаться сделать его короче, если у вас есть проблемы с пространством.
Другие ответы упоминают производительность, и это показывает базовое незнание того, как работают замки.
Когда инициируется попытка блокировки, ядро, о котором идет речь, вызывает сигнал на одном из своих выводов (LOCK), который сообщает всем другим ядрам, их кэшам, всей памяти и всем устройствам управления шинами (поскольку они могут обновлять ОЗУ независимо от ядер), чтобы завершить любые выдающиеся операции памяти. Когда сделав это, они коллективно вызывают другой сигнал-lock Reconnaissance (LOCKA) - который возвращается в исходное ядро и происходит обмен памятью. После этого сигнал блокировки выключается.
Как только вы прибыли сюда, вы можете посмотреть на значение, которое вы получили с помощью xchg. Если выяснится, что другая задача/поток владеет блокировкой, вам нужно будет снова выполнить последовательность блокировки.
Предположим, что самым медленным устройством для управления шиной на вашем компьютере является карта PCI 33 МГц. Если он что-то делает, ему потребуется любое количество тактов шины PCI для завершения. Каждый цикл там означает сто циклов ожидания на процессоре с частотой 3,3 ГГц. Поставьте это в перспективе сохранения цикла или двух в последовательности блокировки. В процессоре, чипсете и материнской плате есть несколько шин, и некоторые из них, все или ни одна из них не могут быть активны в любой момент времени - например, при инициировании блокировки. Активная шина, которая дольше всего отвечает с помощью LOCKA, определяет скорость блокировки завершает.
Попробуйте сами: измерьте, сколько времени требуется, чтобы сделать десять миллионов спин-локов (захватить и отпустить).
Я написал еще несколько о spinlocks здесь, здесь и здесь.
Трюк производительности с шинными блокировками (spinlocks, critical sections in Windows) заключается в том, чтобы использовать их как можно реже, что означает организацию ваших данных, чтобы сделать это возможным. Блокировка шины, скорее всего, завершится быстрее на несерверном компьютере. Это потому, что автобус-мастеринг устройства на сервере работают более или менее постоянно. Таким образом, если ваше приложение основано на сервере, экономия на блокировках шины может иметь решающее значение для поддержания производительности.
EDIT
Питеру Кордесу,
Вы утверждаете, что
... это не связано с освоением шины, по крайней мере, не на процессорах, так как по крайней мере Нехалем
Из последнего руководства по программированию intel System:
8.1.4 влияние операции блокировки на внутренний процессор Кэши
Для процессоров Intel486 и Pentium сигнал блокировки# всегда утверждается на шине во время работы блокировки, даже если площадь заблокированная память кэшируется в процессоре.
Для семейств процессоров P6 и более поздних, если область памяти блокирование во время операции блокировки кэшируется в процессоре, который выполняет операцию блокировки как память обратной записи и является полностью содержится в строке кэша, процессор не может утверждать, что Блокировка# сигнал на автобусе. Вместо этого он изменит расположение памяти внутренне и позволить механизму когерентности кэша гарантировать, что операция проводится атомарно. Эта операция называется " кэширование запирающий."Механизм когерентности кэша автоматически предотвращает два или больше процессоров, которые кэшировали ту же область памяти из одновременно изменяя данные в этой области.
Во втором абзаце говорится
Я не знаю, как вы, но для меня, по крайней мере, "не может" звучит подозрительно непохоже на "не будет" или "не будет". Числа, которые я привел, могут быть правильными или нет - даже я иногда ошибаюсь, - но я призываю вас прекратить цитировать тот или иной" авторитет " и вместо этого пачкать руки, делая работу, чтобы либо опровергнуть мои числа, найти ошибку(ы) или несоответствия. Я включил соответствующий исходный код в другой поток (где я также ворчал по поводу ваших возвышенных, теоретических, основанных на кресле комментариев), так что вам не потребуется вечность, чтобы начать.... процессор не может утверждать сигнал блокировки# на автобусе.
Начните, например, с доказательства того, что я
Завышение стоимости блокировки в случае отсутствия конкуренции ...
Я с нетерпением жду вашего анализа.