它是一个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;
}发布于 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现在为零”。
发布于 2013-08-21 08:04:23
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为空,此函数将“交换”*p和np的内容。
它通过使用cmpxchgq (比较和交换,四字64位)指令来实现这一点,换句话说,将*p (%2)处的64位值与0 (在参数0中,即rax)进行比较,如果rax值与内存位置匹配,则将新值存储在np (%3)中。最后,如果进行了替换,old将包含内存位置中的值,因此我们可以检查替换时它是否为NULL。lock前缀确保处理器独占访问内存,目前没有其他处理器可以写入此位置。
这样做是为了避免在链表末尾插入内容时使用互斥锁。如果有多个线程试图插入,则需要确保在将元素添加到列表末尾时,列表的末尾确实为NULL,否则会出错(特别是,列表将“丢弃”项)。cmpxchg指令是针对这种类型的“如果值是this,则将其替换为另一个值”。
https://stackoverflow.com/questions/18346756
复制相似问题