libatomic_opsのAO_double_t::AO_parts定義
AO_v1とAO_v2逆じゃない?
証拠
(gdb) p/x *addr $4 = { AO_whole = 0x895590c3c908458b, AO_parts = { AO_v1 = 0xc908458b, AO_v2 = 0x895590c3 } }
下でテスト通っちゃうんだよな。
AO_INLINE int my_AO_compare_double_and_swap_double_full(volatile AO_double_t *addr, AO_t old_val1, AO_t old_val2, AO_t new_val1, AO_t new_val2) { int __tmp1, __tmp2; // dummy to show that EDX and ECX registers are used int __ebx; // EBX register backup char result; __asm__ __volatile__( " movl %%ebx, %9\n" " movl %8, %%ebx\n" "lock;\n cmpxchg8b %0\n" " setz %1\n" " movl %9, %%ebx\n" : "=m"(*addr), "=m"(result), "=d"(__tmp1), "=c"(__tmp2) : "m"(*addr), "d" (old_val1), "a" (old_val2), "c" (new_val1), "m"(new_val2), "m"(__ebx) : "memory", "cc"); return (int) result; }
__tmpはGCCのバグ避け。can't find a register in class ‘DREG’ while reloading ‘asm’がでちゃう。
AO_double_t ab; ab.AO_val2 = 10000; ab.AO_val1 = 20000; BOOST_CHECK(my_AO_compare_double_and_swap_double_full( reinterpret_cast<AO_double_t*>(&ab), 10000, 20000, 30000, 40000 ) != 0); // should success // result should be changed BOOST_CHECK_EQUAL(ab.AO_val2, 30000); BOOST_CHECK_EQUAL(ab.AO_val1, 40000); }
あとでもうちょっと詳しく書く。