我遇到了这个旧的(4.8.3之前的GCC-错误60272)错误报告https://gcc.gnu.org/ml/gcc-bugs/2014-02/msg01951.html。现在已修复。但是我对此有疑问。我编译了以下代码片段
#include <atomic>
struct Node { Node* next; };
void Push(std::atomic<Node*>& head, Node* node)
{
node->next = head.load();
while(!head.compare_exchange_weak(node->next, node))
;
}
void Pop(std::atomic<Node*>& head){
for(;;){
Node* value=head.exchange(nullptr);
if(value){
delete value;
break;
}
}
}
与:
g++ -S -std=c++11 -pthread -O3 test.cc -o test.S
生成的程序集具有以下内容(我只列出了相关部分):
.....
4 .L4:
5 lock cmpxchgq %rsi, (%rdi)
6 jne .L6
7 rep ret
8 .p2align 4,,10
9 .p2align 3
10 .L6:
11 movq %rax, (%rsi)
12 jmp .L4
.....
这是我的问题。假设此代码与2个线程并发运行。对于T1,第5行被执行,然后T1被中断,T2做的事情有可能使队列弹出来完成。当OS重新安排T1时,它将从第6行恢复,在执行 jne 之前,有人应该**重新评估**条件。但是,如果不对其进行重新评估,则可能导致内存损坏。我在想正确的方向吗?
最佳答案
cmpxchg指令仅在与dst
匹配时才设置eax
。否则,它将跳转到L6
,更新eax
并重新启动循环。前缀lock允许对当前指令的任何存储器操作数进行独占访问。换句话说,此atomically将节点推送到成功为止。该错误是因为他们最初没有检查结果。
关于c++ - “lock cmpxchg”如何在汇编中工作?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/59020823/