I put the compare_exchangE_weak-code into a noinline function:
struct uip_pair
{
uip_pair() = default;
uip_pair( uintptr_t first, uintptr_t second ) :
first( first ),
second( second )
{
}
uintptr_t first, second;
};
using atomic_pair = atomic<uip_pair>;
#if defined(_MSC_VER)
#define NOINLINE __declspec(noinline)
#elif defined(__GNUC__) || defined(__clang__)
#define NOINLINE __attribute((noinline))
#endif
NOINLINE
bool cmpXchg( atomic_pair &ap, uip_pair &cmp, uip_pair xchg )
{
return ap.compare_exchange_weak( cmp, xchg, memory_order_relaxed,
memory_order_relaxed );
}
?cmpXchg@@YA_NAEAU?$atomic@Uuip_pair@@@std@@AEAUuip_pair@@U3@@Z PROC
cmpXchg, COMDAT
mov eax, 1
mov r10, rcx
mov r9d, eax
xchg DWORD PTR [rcx], eax
test eax, eax
je SHORT $LN14@cmpXchg
$LL13@cmpXchg:
mov eax, DWORD PTR [rcx]
test eax, eax
je SHORT $LN16@cmpXchg
$LL15@cmpXchg:
mov eax, r9d
test r9d, r9d
je SHORT $LN38@cmpXchg
npad 1
$LL19@cmpXchg:
pause
sub eax, 1
jne SHORT $LL19@cmpXchg
cmp r9d, 64
jl SHORT $LN38@cmpXchg
lea r9d, QWORD PTR [rax+64]
jmp SHORT $LN22@cmpXchg
$LN38@cmpXchg:
add r9d, r9d
$LN22@cmpXchg:
mov eax, DWORD PTR [rcx]
test eax, eax
jne SHORT $LL15@cmpXchg
$LN16@cmpXchg:
mov eax, 1
xchg DWORD PTR [rcx], eax
test eax, eax
jne SHORT $LL13@cmpXchg
$LN14@cmpXchg:
mov rax, QWORD PTR [rcx+8]
sub rax, QWORD PTR [rdx]
jne SHORT $LN39@cmpXchg
mov rax, QWORD PTR [rcx+16]
sub rax, QWORD PTR [rdx+8]
$LN39@cmpXchg:
test rax, rax
sete al
test al, al
je SHORT $LN6@cmpXchg
movups xmm0, XMMWORD PTR [r8]
movups XMMWORD PTR [rcx+8], xmm0
xor ecx, ecx
xchg DWORD PTR [r10], ecx
ret 0
$LN6@cmpXchg:
movups xmm0, XMMWORD PTR [rcx+8]
xor ecx, ecx
movups XMMWORD PTR [rdx], xmm0
xchg DWORD PTR [r10], ecx
ret 0
?cmpXchg@@YA_NAEAU?$atomic@Uuip_pair@@@std@@AEAUuip_pair@@U3@@Z ENDP
Maybe someone here understands what the above assembly-code does.