swap_if_null的asm代码

时间:2013-08-20 23:51:52

标签: c++ assembly

这是一个c ++内联asm:

inline bool swap_if_null(head_t **p, head_t *np) {
      register head_t *old;
      asm volatile(
          "lock;\n\t"
          "cmpxchgq %3, %2"
          : "=a"(old)
          : "0"(0), "m"(*p), "r"(np)
          : "memory");
      return old == NULL;
}

2 个答案:

答案 0 :(得分:3)

该函数正在*p上进行原子比较和交换,预计处于状态np,所需的新值为NULL。该函数只执行一次,并返回操作是否成功。

一些解释:机器指令是lock cmpxchgq R, M(在AT& T语法中),其中R是包含新值的寄存器(它是与np相关联的寄存器,如由“%3”表示,即“第三个输入操作数”),M是要修改的内存位置(即“%2”,即“第二个输入操作数” “,即*p)。

新值预计在寄存器%rax中。该寄存器与作为第0个输出操作数的变量old in相关联,但它也是"0"引起的第一个输入操作数,这意味着“与第0个输入操作数相同”。但是在输入时,值不是绑定到变量,而是设置为“0”。也就是说,%rax最初为零,并且在指令old引用它并包含操作结果之后。

根据比较和交换的性质,如果操作成功且%rax保持不变,或者操作失败,则old(以及%rax)将为零内存的当前值为零。在这两种情况下,函数都会返回成功,即“头部现在为零”。

答案 1 :(得分:1)

inline bool swap_if_null(head_t **p, head_t *np) {
  register head_t *old;
  asm volatile(
      "lock;\n\t"
      "cmpxchgq %3, %2"
      : "=a"(old)
      : "0"(0), "m"(*p), "r"(np)
      : "memory");
  return old == NULL;
}

如果*p为NULL,此函数将“交换”np*p的内容。

它通过使用cmpxchgq(比较和交换,四字[64位])指令来执行此操作,换句话说,比较*p%2)处的64位值使用0(在参数0中,即rax),如果rax值与内存位置匹配,则将新值存储在np中,({{1 }})。最后,如果进行了替换,%3包含内存位置中WAS的值,因此我们可以在替换时检查它是否为oldNULL前缀确保处理器具有对内存的独占访问权限,目前没有其他处理器可以写入此位置。

这样做是为了避免在链接列表末尾插入内容时使用互斥锁。如果你有多个线程试图插入,你需要确保列表的末尾在你将元素添加到列表末尾的时候真的是NULL,否则事情就会出错(特别是列表会“丢弃“项目”。 lock指令适用于这种“如果值为this,则将其替换为其他值”。