Я знаю, как атомарно записать значение в x86 ASM. Но как мне его прочитать? Префикс LOCK нельзя использовать с mov.
Чтобы увеличить значение, я делаю:
lock inc dword ptr Counter
Как читать Counter потокобезопасным способом?
Я знаю, как атомарно записать значение в x86 ASM. Но как мне его прочитать? Префикс LOCK нельзя использовать с mov.
Чтобы увеличить значение, я делаю:
lock inc dword ptr Counter
Как читать Counter потокобезопасным способом?
Я не эксперт по ассемблеру, но операции чтения/записи размером в слово (на x86, 32-разрядной версии) уже должны быть атомарными.
Причина, по которой вам нужно заблокировать приращение, заключается в том, что это и чтение, и запись.
mov
загрузка/сохранение является атомарным, если адрес выровнен. x86 имеет согласованные кеши, поэтому даже если несколько процессоров читают/записывают одно и то же место, вы не получите разрыва, если значение не выровнено.
- person Peter Cordes; 01.01.2018
Как я объясню вам в этот< /а> сообщение:
Процессы Intel Core 2 Duo, Intel Core Duo, Pentium M, Pentium 4, Intel Xeon, семейство P6, Pentium и Intel486 не гарантируют, что доступ к кэшируемой памяти, разделенной по ширине шины, строкам кэша и границам страниц, будет атомарным. процессоры. Процессоры семейства Intel Core 2 Duo, Intel Core Duo, Pentium M, Pentium 4, Intel Xeon и P6 обеспечивают сигналы управления шиной, которые позволяют подсистемам внешней памяти делать разделенный доступ атомарным; однако доступ к невыровненным данным серьезно повлияет на производительность процессора, и его следует избегать.
Так что используйте:
LOCK CMPXCHG EAX, [J]
LOCK CMPXCHG сначала выделяет кэш-память, а затем сравнивает EAX с целевым значением, если целевое значение не равно, то результатом в EAX является целевое значение.
РЕДАКТИРОВАТЬ: ССЫЛКИ на:
Руководства для разработчиков программного обеспечения для архитектур Intel® 64 и IA-32
В Том 3A: Руководство по системному программированию см. раздел 8.1.1.
Также проверьте: раздел Справочного руководства по оптимизации: ГЛАВА 7 ОПТИМИЗАЦИЯ ИСПОЛЬЗОВАНИЯ КЭША
mov
load/store является атомарным , если он не пересекает 8-байтовую границу (для кэшированный доступ). Или для некэшированного, если он выровнен, или 16-битный доступ, который не пересекает границу двойного слова. Также [J]
— это просто абсолютный или (в x86-64) относительный режим адресации RIP. Это не двойное обращение. Собирается просто отлично. Синтаксис MASM часто опускает []
, но они необязательны в MASM и обязательны в NASM.
- person Peter Cordes; 01.01.2018
lock cmpxchg
для загрузки. Для статических данных просто используйте ALIGN 4
перед меткой J:
.
- person Peter Cordes; 01.01.2018
Для простого чтения, это в основном о выравнивании. Самый простой способ обеспечить атомарное чтение — всегда использовать «естественное» выравнивание, т. е. выравнивание не меньше размера элемента (например, 32-битный элемент выравнивается по 32-битному).
Смещенные чтения не обязательно являются атомарными. В качестве крайнего примера рассмотрим чтение 32-битного значения по нечетному адресу, где первый байт находится в одной строке кэша, а остальные три байта — в другой строке кэша. В таком случае атомарное чтение практически невозможно.
Поскольку процессоры (по крайней мере, большинство) используют 64-разрядную шину памяти, наибольший элемент, который может быть прочитан атомарно, составляет 64 бита.
Интересно почитать другие ответы. Я думаю, что @GJ, вероятно, при деньгах.
В течение многих лет всегда было верно, что 32-битное чтение и запись были атомарными. Только в последние годы с действительно агрессивным кэшированием это больше не гарантируется.
Думаю, именно поэтому я предпочитаю C++, Java или что-то в этом роде между собой и машинным кодом. В наши дни машинный код слишком сложен, чтобы его можно было надежно написать (если только вы не делаете это много, чтобы не оттачивать свои навыки). К счастью, современные оптимизирующие компиляторы настолько хороши, что вам редко нужна производительность оптимизированного вручную ассемблера.