首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >swap_if_null的asm代码

swap_if_null的asm代码
EN

Stack Overflow用户
提问于 2013-08-21 07:51:52
回答 2查看 203关注 0票数 1

它是一个c++内联asm:

代码语言:javascript
复制
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;
}
EN

回答 2

Stack Overflow用户

发布于 2013-08-21 08:04:12

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

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

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

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

票数 3
EN

Stack Overflow用户

发布于 2013-08-21 08:04:23

代码语言:javascript
复制
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为空,此函数将“交换”*pnp的内容。

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

这样做是为了避免在链表末尾插入内容时使用互斥锁。如果有多个线程试图插入,则需要确保在将元素添加到列表末尾时,列表的末尾确实为NULL,否则会出错(特别是,列表将“丢弃”项)。cmpxchg指令是针对这种类型的“如果值是this,则将其替换为另一个值”。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18346756

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档