Руководство разработчика программного обеспечения для разработчиков Intel® 64 и IA-32:
8.2.3.4 Нагрузки могут быть переупорядочены с более ранними магазинами в разных местах
Модель памяти Intel-64 позволяет загружать нагрузку с более ранним хранилищем в другое место. Однако нагрузки не переупорядочиваются с помощью хранилищ в том же месте.
Что относительно нагрузок, которые частично или полностью перекрывают предыдущие магазины, но не имеют одинакового начального адреса? (См. Конец этого сообщения для конкретного случая)
Предположим, что следующий C-подобный код:
// lock - pointer to an aligned int64 variable
// threadNum - integer in the range 0..7
// volatiles here just to show direct r/w of the memory as it was suggested in the comments
int TryLock(volatile INT64* lock, INT64 threadNum)
{
if (0 != *lock)
return 0; // another thread already had the lock
((volatile INT8*)lock)[threadNum] = 1; // take the lock by setting our byte
if (1LL << 8*threadNum != *lock)
{ // another thread set its byte between our 1st and 2nd check. unset ours
((volatile INT8*)lock)[threadNum] = 0;
return 0;
}
return 1;
}
Или его эквивалент as64 x64:
; rcx - address of an aligned int64 variable
; rdx - integer in the range 0..7
TryLock PROC
cmp qword ptr [rcx], 0
jne @fail
mov r8, rdx
mov rax, 8
mul rdx
mov byte ptr [rcx+r8], 1
bts rdx, rax
cmp qword ptr [rcx], rdx
jz @success
mov byte ptr [rcx+r8], 0
@fail:
mov rax, 0
ret
@success:
mov rax, 1
ret
Тогда предположим, что TryLock выполняется одновременно в двух потоках:
INT64 lock = 0;
void Thread_1() { TryLock(&lock, 1); }
void Thread_5() { TryLock(&lock, 5); }
Вопрос:
Хранилища ((INT8*)lock)[1] = 1;
и ((INT8*)lock)[5] = 1;
не находятся в том же месте, что и 64-разрядная загрузка lock
. Тем не менее, каждая из них полностью заполнена этой нагрузкой, так же как "подсчитывается" как одно и то же местоположение? Кажется невозможным, чтобы процессор мог это сделать.
Как насчет ((INT8*)lock)[0] = 1
? Адрес магазина тогда совпадает с адресом следующей загрузки. Являются ли эти операции "в одном месте", даже если предыдущий случай не был?
p.s. обратите внимание, что вопрос не о коде C/Asm, о поведении процессоров x86.