“ cmpxchg锁”如何在装配中工作?

问题描述 投票:2回答:1

[我遇到了这个旧的(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;
        }
    }
}

with:

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之前重新评估条件。但是,如果不对其进行重新评估,则可能导致内存损坏。我在想正确的方向吗?

c++ gcc assembly x86 x86-64
1个回答
0
投票

cmpxchg指令仅在与dst匹配时才设置eax。否则它将跳到L6,这将更新eax并重新开始循环。 lock前缀允许对当前指令的任何存储器操作数进行独占访问。换句话说,这只是spinlock推动节点。

© www.soinside.com 2019 - 2024. All rights reserved.