Is std::atomic_compare_exchange_weak thread-unsafe by design?

后端 未结 5 1781
北海茫月
北海茫月 2020-12-28 17:47

It was brought up on cppreference atomic_compare_exchange Talk page that the existing implementations of std::atomic_compare_exchange_weak compute the boolea

5条回答
  •  青春惊慌失措
    2020-12-28 18:47

    I was the one who originally found this bug. For the last few days I have been e-mailing Anthony Williams regarding this issue and vendor implementations. I didn't realize Cubbi had raise a StackOverFlow question. It's not just Clang or GCC it's every vendor that is broken (all that matters anyway). Anthony Williams also author of Just::Thread (a C++11 thread and atomic library) confirmed his library is implemented correctly (only known correct implementation).

    Anthony has raised a GCC bug report http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60272

    Simple example:

       #include 
       struct Node { Node* next; };
       void Push(std::atomic head, Node* node)
       {
           node->next = head.load();
           while(!head.compare_exchange_weak(node->next, node))
               ;
       }
    

    g++ 4.8 [assembler]

           mov    rdx, rdi
           mov    rax, QWORD PTR [rdi]
           mov    QWORD PTR [rsi], rax
       .L3:
           mov    rax, QWORD PTR [rsi]
           lock cmpxchg    QWORD PTR [rdx], rsi
           mov    QWORD PTR [rsi], rax !!!!!!!!!!!!!!!!!!!!!!!
           jne    .L3
           rep; ret
    

    clang 3.3 [assembler]

           movq    (%rdi), %rcx
           movq    %rcx, (%rsi)
       .LBB0_1:
           movq    %rcx, %rax
           lock
           cmpxchgq    %rsi, (%rdi)
           movq    %rax, (%rsi) !!!!!!!!!!!!!!!!!!!!!!!
           cmpq    %rcx, %rax !!!!!!!!!!!!!!!!!!!!!!!
           movq    %rax, %rcx
           jne    .LBB0_1
           ret
    

    icc 13.0.1 [assembler]

           movl      %edx, %ecx
           movl      (%rsi), %r8d
           movl      %r8d, %eax
           lock
           cmpxchg   %ecx, (%rdi)
           movl      %eax, (%rsi) !!!!!!!!!!!!!!!!!!!!!!!
           cmpl      %eax, %r8d !!!!!!!!!!!!!!!!!!!!!!!
           je        ..B1.7
       ..B1.4:
           movl      %edx, %ecx
           movl      %eax, %r8d
           lock
           cmpxchg   %ecx, (%rdi)
           movl      %eax, (%rsi) !!!!!!!!!!!!!!!!!!!!!!!
           cmpl      %eax, %r8d !!!!!!!!!!!!!!!!!!!!!!!
           jne       ..B1.4
       ..B1.7:
           ret
    

    Visual Studio 2012 [No need to check assembler, MS uses _InterlockedCompareExchange !!!]

       inline int _Compare_exchange_seq_cst_4(volatile _Uint4_t *_Tgt, _Uint4_t *_Exp, _Uint4_t _Value)
       {    /* compare and exchange values atomically with
           sequentially consistent memory order */
           int _Res;
           _Uint4_t _Prev = _InterlockedCompareExchange((volatile long
    *)_Tgt, _Value, *_Exp);
           if (_Prev == *_Exp) !!!!!!!!!!!!!!!!!!!!!!!
               _Res = 1;
           else
           { /* copy old value */
               _Res = 0;
               *_Exp = _Prev;
           }
           return (_Res);
       }
    

提交回复
热议问题