c++ - 确保使用双重比较和交换指令,用于无锁堆栈?

标签 c++ multithreading assembly x86 lock-free

(假设64位x86-64架构和Intel第3/4代CPU)

这是《Concurrency in Action》一书第 202 页中堆栈的无锁实现:

template<typename T>
class lock_free_stack
{
private:
    struct node;

    struct counted_node_ptr
    {
        int external_count;
        node* ptr;
    };

    struct node
    {
        std::shared_ptr<T> data;
        std::atomic<int> internal_count;
        counted_node_ptr next;

        node(T const& data_):data(std::make_shared<T>(data_)),internal_count(0){}
    };

    std::atomic<counted_node_ptr> head;

public:
    ~lock_free_stack()
    {
        while(pop());
    }

    void push(T const& data)
    {
        counted_node_ptr new_node;
        new_node.ptr=new node(data);
        new_node.external_count=1;
        new_node.ptr->next=head.load();
        while(!head.compare_exchange_weak(new_node.ptr->next,new_node));
    }
};

它在代码下面说:

On those platforms that support a double-word-compare-and-swap operation, this structure will be small enough for std::atomic to be lock-free.

我相信 x86-64 确实支持双 CAS(我记不起指令的名称)。

如果我要检查汇编(并且我看不到双 CAS 指令),我需要编写什么内联汇编函数来确保使用双 CAS?

更新 - 我想我在这里找到了我要找的东西:

http://blog.lse.epita.fr/articles/42-implementing-generic-double-word-compare-and-swap-.html

template<typename T>
struct DPointer <T,sizeof (uint64_t)> {
public:
  union {
    uint64_t ui[2];
    struct {
      T* ptr;
      size_t count;
    } __attribute__ (( __aligned__( 16 ) ));
  };

  DPointer() : ptr(NULL), count(0) {}
  DPointer(T* p) : ptr(p), count(0) {}
  DPointer(T* p, size_t c) : ptr(p), count(c) {}

  bool cas(DPointer<T,8> const& nval, DPointer<T,8> const& cmp)
  {
    bool result;
    __asm__ __volatile__ (
        "lock cmpxchg16b %1\n\t"
        "setz %0\n"
        : "=q" ( result )
         ,"+m" ( ui )
        : "a" ( cmp.ptr ), "d" ( cmp.count )
         ,"b" ( nval.ptr ), "c" ( nval.count )
        : "cc"
    );
    return result;
  }

  // We need == to work properly
  bool operator==(DPointer<T,8> const&x)
  {
    return x.ptr == ptr && x.count == count;
  }
};

最佳答案

x86_64 的最旧版本不支持此指令 (CMPXCHG16B),而 Windows 8.1/64 位及更新版本需要此指令。 Afaik 这是 Athlon64 系列的大部分(插槽 751、939 和一些 X2,也许第一代(8xx)奔腾 D)

如何强制编译器使用特定指令各不相同,通常必须使用不完全可移植的内在指令。

关于c++ - 确保使用双重比较和交换指令,用于无锁堆栈?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23971761/

相关文章:

c++ - 用C++中的字符串替换空格

c++ - 如果已知 void* 分配大小,如何将确切的内存大小传递给 free()

c++ - 如何在 C++ 程序中捕获 strace 的输出

c - OpenMP 嵌套 For 循环竞争条件

java - Spring Quartz 计划任务在一段时间后停止运行

c++ - 从 ASM(汇编 64 位)C++ 中获取值(value)

C++ 单例类 getInstance(作为 java)

java - java中执行程序服务的范围?

assembly - 我应该如何表示要在彩色计算机程序中使用的霍夫曼树?

c - 汇编中的 lea 运算符使用寄存器的三参数算术